簡體   English   中英

Marshal.StructureToPtr在模塊ntdll.dll中失敗

[英]Marshal.StructureToPtr fails in module ntdll.dll

我會從一些歷史開始 :我現在面臨的問題突然出現,而代碼沒有任何更改。 然后在3天后以相同的方式消失。 現在它在一周內回來了,不想消失=)。

我有適用於打印機的代碼 -設置打印機的首選項以指定方式打印文檔。 我使用本地打印機,它指向網絡打印機的TCP地址(據我所知,這是執行此類任務的常用方法)。

以下是我用來從二進制文件加載打印機配置的代碼 (以前以類似的方式保存)。 我為所有源代碼提供了非托管函數調用的聲明,因為不知道是什么原因導致了問題。 阻止我的應用程序的行(Windows服務):

Marshal.StructureToPtr(pInfo, pPInfo, true); //THIS LINE FAILS

這是一個函數的完整代碼:

public static bool LoadSettings(string printerName, string filepath)
{
    Logger.GetLog().WriteInformation(string.Format("Loading printer settings '{0}' for printer '{1}'", filepath, printerName), "PrinterSettingsStorage.LoadSettings()");
    bool success = false;
    try
    {
        if (!File.Exists(filepath))
        {
            return false;
        }

        IntPtr hPrinter;
        int bytes = 0;
        IntPtr pPInfo;
        IntPtr pDevMode;
        PRINTER_INFO_2 pInfo = new PRINTER_INFO_2();

        PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS();
        PrinterValues.pDatatype = 0;
        PrinterValues.pDevMode = 0;
        PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;

        //retrieve the devmode from file
        using (FileStream fs = new FileStream(filepath, FileMode.Open))
        {
            int length = Convert.ToInt32(fs.Length);
            pDevMode = GlobalAlloc(0, length);
            for (int i = 0; i < length; i++)
            {
                Marshal.WriteByte(pDevMode, i, (byte)fs.ReadByte());
            }
        }

        //get printer handle
        OpenPrinter(printerName, out hPrinter, ref PrinterValues);

        //get bytes for printer info structure and allocate memory
        GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out bytes);
        if (bytes == 0)
        {
            throw new Exception("Get Printer Failed");
        }
        pPInfo = GlobalAlloc(0, bytes);

        //set pointer to printer info
        GetPrinter(hPrinter, 2, pPInfo, bytes, out bytes);

        //place the printer info structure
        pInfo = (PRINTER_INFO_2)Marshal.PtrToStructure(pPInfo, typeof(PRINTER_INFO_2));

        //insert the new devmode
        pInfo.pDevMode = pDevMode;
        pInfo.pSecurityDescriptor = IntPtr.Zero;

        //set pointer to new printer info
        Marshal.StructureToPtr(pInfo, pPInfo, true); //THIS LINE FAILS

        //update
        SetPrinter(hPrinter, 2, pPInfo, 0);

        //free resources
        GlobalFree(pPInfo);
        GlobalFree(pDevMode);
        ClosePrinter(hPrinter);

        success = true;
    }
    catch (COMException ce)
    {
        Logger.GetLog().WriteError(string.Format("COM error loading printer settings to printer: {0}", Marshal.GetLastWin32Error()), ce.StackTrace, "PrinterSettingsStorage.LoadSettings()");
    }
    catch (Exception e)
    {
        Logger.GetLog().WriteError(string.Format("Unknown error loading printer settings to printer"), e.StackTrace, "PrinterSettingsStorage.LoadSettings()");
    }
    finally
    {
        Logger.GetLog().WriteInformation(string.Format("Finish loading printer settings '{0}' for printer '{1}'. Success: {2}", printerName, filepath, success), "PrinterSettingsStorage.LoadSettings()");
    }
    return success;
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINTER_DEFAULTS
{
    public int pDatatype;
    public int pDevMode;
    public int DesiredAccess;
}

[StructLayout(LayoutKind.Sequential)]
internal struct PRINTER_INFO_2
{
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pServerName;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pPrinterName;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pShareName;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pPortName;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pDriverName;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pComment;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pLocation;
    public IntPtr pDevMode;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pSepFile;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pPrintProcessor;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pDatatype;
    [MarshalAs(UnmanagedType.LPStr)]
    public readonly string pParameters;
    public IntPtr pSecurityDescriptor;
    public readonly Int32 Attributes;
    public readonly Int32 Priority;
    public readonly Int32 DefaultPriority;
    public readonly Int32 StartTime;
    public readonly Int32 UntilTime;
    public readonly Int32 Status;
    public readonly Int32 cJobs;
    public readonly Int32 AveragePPM;
}

[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GlobalFree(IntPtr handle);

[DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true,
    CharSet = CharSet.Ansi, ExactSpelling = true,
    CallingConvention = CallingConvention.StdCall)]
private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel,
                                        IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);

[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA",
    SetLastError = true, CharSet = CharSet.Ansi,
    ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool
    OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
                out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);

[DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr pPrinter, int Command);

[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true,
    ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool ClosePrinter(IntPtr hPrinter);

症狀:

  • 服務只是立即停止在參考行退出。 沒有finally塊執行,沒有捕獲異常。

  • Windows事件日志包含錯誤

    故障模塊名稱:ntdll.dll,版本:6.1.7601.17725,時間戳:0x4ec49b8f異常代碼:0xc0000374故障偏移量:0x000ce6c3故障進程ID:0x12dc故障應用程序啟動時間:0x01cdc71b9bf9b661故障應用程序路徑:C:\\ Program Files(x86)\\ MyServiceExePath.exe錯誤的模塊路徑:C:\\ Windows \\ SysWOW64 \\ ntdll.dll報告ID:0eb45111-330f-11e2-be8e-005056975a30

我的操作系統:Windows Server 2008 R2。

就像我說的,它會在一段時間內不斷復制,然后消失而無需更改代碼。 我不知道是什么原因導致了這個問題,為什么它如此不穩定。 希望這里有人比我更了解非托管代碼。

有任何想法嗎?

        //insert the new devmode
        pInfo.pDevMode = pDevMode;
        pInfo.pSecurityDescriptor = IntPtr.Zero;

        //Add by me
        Marshal.StructureToPtr(pInfo, pPInfo, false);
        //set pointer to new printer info 
        Marshal.StructureToPtr(pInfo, pPInfo, true);

        //update
        SetPrinter(hPrinter, 2, pPInfo, 0);
        //Add by me
        Marshal.DestroyStructure(pPInfo, typeof(PRINTER_INFO_2));

        //free resources
        GlobalFree(pPInfo);
        GlobalFree(pDevMode);
        ClosePrinter(hPrinter);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM