SetJob()方法总是返回122

我正在编写一个C#程序来改变打印作业的方向。 我是这样做的

•使用OpenPrinter打开打印机()

•使用GetJob()获取JOB_INFO_2结构的作业详细信息

•更改JOB_INFO_2结构中的方向

•使用SetJob()设置JOB_INFO_2结构

但是当我调用SetJob()方法时,它总是失败并返回代码122.我用PRINTER_ALL_ACCESS打开打印机。 (我也尝试过PRINTER_ACCESS_ADMINISTER,但没有运气)。 我使用的打印机是本地打印机。

我究竟做错了什么?

这是我的代码

public class PrintJob { #region Native Method Imports [DllImport("winspool.drv", EntryPoint = "OpenPrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] public static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, ref PRINTER_DEFAULTS pDefault); [DllImport("winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] public static extern bool ClosePrinter(IntPtr hPrinter); [DllImport("winspool.drv", EntryPoint = "GetJob", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] public static extern bool GetJob(IntPtr hPrinter, Int32 dwJobId, Int32 Level, IntPtr lpJob, Int32 cbBuf, ref Int32 lpbSizeNeeded); [DllImport("winspool.drv", EntryPoint = "GetJob", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)] public static extern bool GetJob(Int32 hPrinter, Int32 dwJobId, Int32 Level, IntPtr lpJob, Int32 cbBuf, ref Int32 lpbSizeNeeded); [DllImport("winspool.drv", EntryPoint = "SetJobA")] public static extern bool SetJob(IntPtr hPrinter, int JobId, int Level, IntPtr pJob, int Command_Renamed); [StructLayout(LayoutKind.Sequential)] internal struct PRINTER_DEFAULTS { public int pDatatype; public int pDevMode; public uint DesiredAccess; } private const int DM_ORIENTATION = 0x1; #endregion public void ChangePrintOrientation(string printerName, int jobId) { IntPtr _printerHandle = IntPtr.Zero; PRINTER_DEFAULTS pDefaults = new PRINTER_DEFAULTS(); pDefaults.DesiredAccess = 0xf000c; // PRINTER_ALL_ACCESS; pDefaults.pDatatype = 0; pDefaults.pDevMode = 0; //Open the printer OpenPrinter(printerName, out _printerHandle, ref pDefaults); if (_printerHandle == IntPtr.Zero) { throw new Exception("OpenPrinter() Failed with error code " + Marshal.GetLastWin32Error()); } //Get the JOB details from GetJob() JOB_INFO_2 jobInfo = GetJobInfo2(_printerHandle, jobId); if(jobInfo == null) { throw new Exception("Could not get job details"); } //Set the orientation jobInfo.DeviceMode.dmFields = DM_ORIENTATION; jobInfo.DeviceMode.dmOrientation = 2;//LANDSCAPE IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(jobInfo)); Marshal.StructureToPtr(jobInfo, ptr, false); //Set the job if(!SetJob(_printerHandle, jobId, 2, ptr, 0)) //Here i always get 122 from the function { throw new Exception("SetJob() Failed with error code " + Marshal.GetLastWin32Error()); } //Finally close the printer ClosePrinter(_printerHandle); } private JOB_INFO_2 GetJobInfo2(IntPtr _printerHandle, int jobId) { JOB_INFO_2 info = null; Int32 BytesWritten = default(Int32); IntPtr ptBuf = default(IntPtr); //Get the required buffer size if (!GetJob(_printerHandle, jobId, 2, ptBuf, 0, ref BytesWritten)) { if (BytesWritten == 0) { throw new Exception("GetJob for JOB_INFO_2 failed on handle: " + _printerHandle.ToString() + " for job: " + jobId); } } //Allocate a buffer the right size if (BytesWritten > 0) { ptBuf = Marshal.AllocHGlobal(BytesWritten * 2); } if (!GetJob(_printerHandle, jobId, 2, ptBuf, BytesWritten, ref BytesWritten)) { throw new Exception("GetJob for JOB_INFO_2 failed on handle: " + _printerHandle.ToString() + " for job: " + jobId); } else { info = new JOB_INFO_2(); Marshal.PtrToStructure(ptBuf, info); //Fill the devmode structure IntPtr ptrDevMode = new IntPtr(info.LPDeviceMode); Marshal.PtrToStructure(ptrDevMode, info.dmOut); } //\\ Free the allocated memory Marshal.FreeHGlobal(ptBuf); return info; } } 

我从这里开始使用DEVMODE结构。

这段代码有效。 它删除了打印作业。

  BOOL JobControlPause(wstring strPrinterName) { PRINTER_DEFAULTS pd; ZeroMemory(&pd, sizeof(pd)); pd.DesiredAccess = PRINTER_ALL_ACCESS; DWORD dwSize; char szPrinterName[100]; BOOL bOK; HANDLE hPrinter = NULL; PRINTER_INFO_2 *pPrinterInfo = NULL; DWORD dwReturned, dwNeeded, dwJobCount; JOB_INFO_2 *pJobInfo; dwSize = 100; //// default printer //GetProfileString("windows", "device", "", szPrinterName, dwSize); //// Printer name precedes first "," character... //strtok(szPrinterName, ","); // get the printer handle bOK = OpenPrinter((LPWSTR)strPrinterName.c_str(), &hPrinter, &pd); if (!bOK) return 1; // get byte count needed for buffer GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded); // alocate the buffer pPrinterInfo = new PRINTER_INFO_2[dwNeeded +5]; // get an information about the printer bOK = GetPrinter(hPrinter, 2, (LPBYTE)pPrinterInfo, dwNeeded, &dwReturned); if (!bOK) return FALSE; // alocate the structure EnumJobs(hPrinter, 0, pPrinterInfo->cJobs, 2, NULL, 0, (LPDWORD)&dwNeeded, (LPDWORD)&dwReturned); pJobInfo = new JOB_INFO_2[dwNeeded]; // enum the jobs if (!EnumJobs(hPrinter, 0, pPrinterInfo->cJobs, 2, (LPBYTE)pJobInfo, dwNeeded, &dwReturned, &dwJobCount)) { return 1; } // pause all jobs for (DWORD i=0; i 

返回值基于以下规则:如果函数成功,则返回值为非零值。 如果函数失败,则返回值为零。

而你的代码是:if(!SetJob(_printerHandle,jobId,2,ptr,0))//这里我总是从函数中获取122 {throw new Exception(“SetJob()失败,错误代码为”+ Marshal.GetLastWin32Error( )); }

这意味着当SetJob ruturn成功时,代码抛出exception