Six_Rabbit 2024-11-15 10:17 采纳率: 0%
浏览 15
已结题

在使用Marshal.AllocHGlobal分配内存之后,进入NET方法后转换成结构内容与外层代码完全不一致

请勿使用AIGC类型回答,鄙人会用AI;AIGC类型回答一律不采纳;不要™用AIGC回答

进入源码调试后发现使用SetHdevmode()方法之后的,传入的地址没变,但是转为DEVMODE结构内容与代码中的内容完全不一致,暂时不知道如何解决。

/// <summary>
/// 设置打印机
/// </summary>
public void SettingPrint(PrinterSet printerSet)
{
    DEVMODE dm;
    IntPtr devModePtr = IntPtr.Zero;

    try
    {
        // 正式获取结构体
        GetDevModPtr(out devModePtr);
        GetDevMode(devModePtr, out dm);

        // 修改内容
        dm.ExDevMode[DevModeCode.ExDevTop + DevModeCode.ExCut2inch] = printerSet.Cut2inch;

        // 将修改之后dm同步内存
        Marshal.StructureToPtr(dm, devModePtr, true);

        pd.PrinterSettings.SetHdevmode(devModePtr);
    }
    finally 
    {
        if (devModePtr != IntPtr.Zero) 
        {
            Marshal.FreeHGlobal((IntPtr)devModePtr);
        }
    }
}

/// <summary>
/// 手动获取DEVMOD指针
/// </summary>
/// <param name="devModePtr"> 等待分配的指针 </param>
/// <exception cref="Exception"></exception>
public void GetDevModPtr(out IntPtr devModePtr)
{
    // 空默认不使用
    IntPtr tempNull = new IntPtr();
    int devSize;

    devSize = FunctionClass.DocumentProperties(IntPtr.Zero, printerSlef, printName, tempNull, ref tempNull, 0);

    // 分配内存大小
    devModePtr = Marshal.AllocHGlobal(devSize + 1260);
    // 是否获取成功
    if (devModePtr == IntPtr.Zero)
    {
        throw new Exception("Cannot get DevMode Intptr");
    }
}

/// <summary>
/// 手动获取DevMod内容
/// </summary>
/// <param name="devModePtr"> 已被分配内存的指针 </param>
/// <param name="dm"> 回传结构体 </param>
/// <exception cref="Exception"></exception>
public void GetDevMode(IntPtr devModePtr, out DEVMODE dm)
{
    IntPtr tempNull = IntPtr.Zero;
    int resultCode;

    // 再次访问获取实际数据
    resultCode = FunctionClass.DocumentProperties(0, printerSlef, printName, devModePtr, ref tempNull, DevModeCode.DM_OUT_BUFFER);
    if (resultCode < 0)
    {
        throw new Exception("Cannot get DevMode"); ;
    }

    dm = Marshal.PtrToStructure<DEVMODE>(devModePtr);
}

  • 写回答

28条回答 默认 最新

  • 阿里嘎多学长 2024-11-15 10:28
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    问题分析 使用 winspool.drvSetPrinter 函数设置打印机失败,Marshal.GetLastPInvokeError() 错误码为 1。

    可能原因 在使用 SetPrinter 函数设置打印机时,可能出现以下几种错误:

    1. 打印机不存在或未连接
    2. 打印机已经被占用
    3. 无权限访问打印机

    解决方案 可以尝试以下方法解决问题:

    1. 确认打印机是否存在或已经连接
    2. 使用 SetPrinter 函数时,添加超时时间来等待打印机释放
    3. 检查权限,确保当前用户具有访问打印机的权限

    代码示例

    [DllImport("winspool.drv", EntryPoint = "SetPrinter")]
    private static extern bool SetPrinter([MarshalAs(UnmanagedType.LPTStr)] string printerName, [MarshalAs(UnmanagedType.LPTStr)] string printerName2, ref PRINTER_DEFAULTS printerDefaults);
    
    [StructLayout(LayoutKind.Sequential)]
    public struct PRINTER_DEFAULTS
    {
        public int pDatatype;
        public int pDevMode;
    }
    
    // 使用 SetPrinter 函数设置打印机
    PRINTER_DEFAULTS pd = new PRINTER_DEFAULTS();
    // ... 设置打印机默认值 ...
    bool result = SetPrinter(printerName, printerName2, ref pd);
    

    在上面的代码中,我们使用 DllImport 属性将 SetPrinter 函数导入到 C# 中,并使用 StructLayout 属性将 PRINTER_DEFAULTS 结构体布局到内存中。然后,我们使用 SetPrinter 函数设置打印机,具体的打印机名称和默认值请自行实现。

    总结 使用 winspool.drvSetPrinter 函数设置打印机失败可能由多种原因引起,我们可以尝试添加超时时间、检查权限和确认打印机存在或连接等方法来解决问题。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月18日
  • 修改了问题 11月18日
  • 修改了问题 11月15日
  • 修改了问题 11月15日
  • 展开全部

悬赏问题

  • ¥15 微信小程序:渲染收货地址时页面不显示
  • ¥20 win7 64位DirectShow提示初始化失败如何解决?
  • ¥20 小规模孤立词识别系统设计
  • ¥15 关于Java对接海康威视车牌识别一体机SDK是否需要固定外网的IP?
  • ¥15 Linux扩容时,格式化卡住了:vgdispaly查看卷组信息,没有输出
  • ¥18 关于#ubuntu#的问题:使用背景-工作职责内有七八台ubuntu系统的电脑,平时需要互相调取资料,想实现把这几台电脑用交换机组成一个局域网,来实现指定文件夹的互相调取和写入
  • ¥20 求一个简易射频信号综测仪
  • ¥15 esp8266 tally灯 接收端改为发射端
  • ¥30 Labview代码调用access 数据库,相同代码其中一个调用不出来是为什么
  • ¥15 基于51单片机的交通灯系统,找改程序有点急