C# SetJob()方法始终返回122
我正在写一个C程序来改变打印作业的方向。 下面是我是怎么做的 •使用OpenPrinter打开打印机 •使用GetJob获取具有job_INFO_2结构的job详细信息 •更改作业信息结构中的方向 •使用SetJob设置作业信息2结构 但当我调用SetJob方法时,它总是失败,返回代码为122。 我正在使用打印机访问权限打开打印机。我也尝试过打印机访问管理,但运气不好。我正在使用的打印机是本地打印机 我做错了什么 这是我的密码C# SetJob()方法始终返回122,c#,printing,C#,Printing,我正在写一个C程序来改变打印作业的方向。 下面是我是怎么做的 •使用OpenPrinter打开打印机 •使用GetJob获取具有job_INFO_2结构的job详细信息 •更改作业信息结构中的方向 •使用SetJob设置作业信息2结构 但当我调用SetJob方法时,它总是失败,返回代码为122。 我正在使用打印机访问权限打开打印机。我也尝试过打印机访问管理,但运气不好。我正在使用的打印机是本地打印机 我做错了什么 这是我的密码 public class PrintJob { #regio
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<dwJobCount; i++)
{
bOK = SetJob(hPrinter, pJobInfo[i].JobId, 2, (LPBYTE)pJobInfo, JOB_CONTROL_DELETE);
if (!bOK)
{
//MessageBox(NULL, "Error", "Error", MB_OK);
return FALSE;
}
}
return TRUE;
}
返回值基于以下规则: 如果函数成功,则返回值为非零值。 如果函数失败,则返回值为零 而您的代码是: 如果SetJob_printerHandle,jobId,2,ptr,0//这里我总是从函数中得到122 { 抛出新异常SetJob失败,错误代码为+Marshal.GetLastWin32Error; }
这意味着当SetJob ruturn成功时,代码抛出异常我猜JOB\u INFO\u 2的声明是错误的。使用Marshal.SizeOf验证大小。32位模式下为104字节,64位模式下为160字节。我检查了JOB_INFO_2的大小,仅为104字节。@Prasad:请发布JOB_INFO_2结构的定义好吗?JOB_INFO_2结构的实现是什么?此GetJob定义在64位上似乎不起作用?