我将从一点历史:我目前面临的问题是突然出现的,没有对代码进行任何更改。 3天后又以同样的方式消失。现在它一周后就回来了并且不想消失=)。
I have 适用于打印机的代码- 设置打印机首选项以指定方式打印文档。我使用本地打印机,它指向网络打印机的 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。
正如我所说,它会在一段时间内不断重现,然后在代码没有任何更改的情况下消失一次。我不知道是什么原因导致这个问题以及为什么它如此不稳定。希望这里有人比我对非托管代码更有经验=)。
有任何想法吗?