How to change username of job in print queue using python & win32print
Asked Answered
F

1

1

I am trying to change the user of a print job in the queue, as I want to create it on a service account but send the job to another users follow-me printing queue. I'm using the win32 module in python. Here is an example of my code:

from win32 import win32print

JOB_INFO_LEVEL = 2
pclExample = open("sample.pcl")
printer_name = win32print.GetDefaultPrinter()
hPrinter = win32print.OpenPrinter(printer_name)

try:
    jobID = win32print.StartDocPrinter(hPrinter, 1, ("PCL Data test", None, "RAW"))
    # Here we try to change the user by extracting the job and then setting it again
    jobInfoDict = win32print.GetJob(hPrinter, jobID , JOB_INFO_LEVEL )
    jobInfoDict["pUserName"] = "exampleUser"
    win32print.SetJob(hPrinter, jobID , JOB_INFO_LEVEL  , jobInfoDict , win32print.JOB_CONTROL_RESUME )

    try:
        win32print.StartPagePrinter(hPrinter)
        win32print.WritePrinter(hPrinter, pclExample)
        win32print.EndPagePrinter(hPrinter)

    finally:
        win32print.EndDocPrinter(hPrinter)
finally:
    win32print.ClosePrinter(hPrinter)
    

The problem is I get an error at the win32print.SetJob() line. If JOB_INFO_LEVEL is set to 1, then I get the following error:

(1804, 'SetJob', 'The specified datatype is invalid.')

This is a known bug to do with how the C++ works in the background (Issue here).

If JOB_INFO_LEVEL is set to 2, then I get the following error:

(1798, 'SetJob', 'The print processor is unknown.')

However, this is the processor that came from win32print.GetJob(). Without trying to change the user this prints fine, so I'm not sure what is wrong.

Any help would be hugely appreciated! :)

EDIT:

Using Python 3.8.5 and Pywin32 303

Fortunia answered 25/3, 2022 at 5:38 Comment(3)
Perhaps It's a pywin32 issue but I haven’t verified SetJob function.Numb
What are your Python and PyWin32 versions?Protest
Using Python 3.8.5 and Pywin32 303 - Just added to original postFortunia
P
1

At the beginning I thought it was a misunderstanding (I was also a bit skeptical about the bug report), mainly because of the following paragraph (which apparently seems to be wrong) from [MS.Docs]: SetJob function (emphasis is mine):

The following members of a JOB_INFO_1, JOB_INFO_2, or JOB_INFO_4 structure are ignored on a call to SetJob: JobId, pPrinterName, pMachineName, pUserName, pDrivername, Size, Submitted, Time, and TotalPages.

But I did some tests and ran into the problem. The problem is as described in the bug: filling JOB_INFO_* string members (which are LPTSTRs) with char* data.

Submitted [GitHub]: mhammond/pywin32 - Fix: win32print.SetJob sending ANSI to UNICODE API (and none of the 2 errors pops up). It was merged to main on 220331.

When testing the fix, I was able to change various properties of an existing job, I was amazed that it didn't have to be valid data (like below), I'm a bit curious to see what would happen when the job would be executed (as now I don't have a connection to a printer):

  • Change pUserName to str(random.randint(0, 10000)) to make sure it changes on each script run (PrintScreens taken separately and assembled in Paint):

    img0

Ways to go further:

  1. Wait for a new PyWin32 version (containing this fix) to be released. This is the recommended approach, but it will also take more time (and it's unclear when it will happen)

  2. Get the sources, either:

  • from main

  • from b303 (last stable branch), and apply the (above) patch(1)

    build the module (.pyd) and copy it in the PyWin32's site-packages directory on your Python installation(s). Faster, but it requires some deeper knowledge, and maintenance might become a nightmare



Footnotes

Protest answered 30/3, 2022 at 22:27 Comment(2)
Thanks Cristi - I've marked this as accepted as it solved the issue and I now have access to changing the user. I was wondering what JOB_CONTROL_* variable you passed into the job control parameter to change the user? I am able to execute the command, but it doesn't change the owner in the queue.Fortunia
I didn't pay attention to that detail, I just used whatever value was in the script in the bug report URL, and that is 0. "You can use the same call to the SetJob function to set print job parameters and to give a command to a print job. Thus, Command does not need to be 0 if you are setting print job parameters, although it can be."Protest

© 2022 - 2024 — McMap. All rights reserved.