English 中文(简体)
SetJob() A. 方法
原标题:SetJob() Method always returns 122
  • 时间:2011-11-10 16:03:43
  •  标签:
  • c#
  • printing

I am writing a C# program to change the orientation of print job. Here is how I am doing it

• 使用开放式印刷机

• 利用GetJob()与JOB_INFO_2结构取得工作详情

• 改变JOB-INFO_2结构的方向

• 利用SetaJob()建立JOB_INFO_2结构

But when I call SetJob() method it always fails with the return code 122. I am opening printer with PRINTER_ALL_ACCESS. (I have also tried with PRINTER_ACCESS_ADMINISTER but no luck). The printer I am using is local printer.

我做了什么错误?

我的法典

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;
    }
}

我从here上接过了DEVODE结构。

问题回答

该法典行之有效。 它删除了印刷工作。

   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;
}

the return value is based the following rule: If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero.

while your code is : 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()); }

也就是说,当PetJob ruturn提出诉讼时,法律将出现例外情况。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签