Search code examples
winapiprintingpywin32

PRINTER_INFO_6 not available using WIn32 api


I have been trying to get printer status from a DNP rx1 printer, but the status of the printer does not change when I open the tray of the printer. Here is an example using py32win library to access the status and it always return status = 0 event when the tray is open.

device_name = win32print.GetDefaultPrinter()
handle = win32print.OpenPrinter(device_name)

# Get the default properties for the printer
properties = win32print.GetPrinter(handle, 2)

When I try win32print.GetPrinter(handle, 6) # 6 = print_info_6 I get the some NotImplementedException. So my guess is that the firmware of the printer have not implemented print_info_6. So I can't get the status from the printer

I have also tried using powershell with:

Get-Printer | Select Name, PrinterStatus

Also no change in status when I open the tray or if there is a paper jam.

Is there anything that I'm overlooking? Is there anything else I can try to get the status of the printer?


Solution

  • PRINTER_INFO_6 works for me in C++ on Windows 10 1903 with OneNote printer.

    enter image description here

    And when I pause the printer I get status 0x00000001 (PRINTER_STATUS_PAUSED).

    enter image description here

    The C++ code I used for testing.

    #pragma comment(lib, "Winspool")
    
    int main()
    {
        DWORD bufSize;
        WCHAR* buf = NULL;
        HANDLE hPrinter = NULL;
        PRINTER_INFO_6 info = {};
        DWORD needed;
        BOOL result = FALSE;
        DWORD err;
    
        // Get required buffer size
        result = GetDefaultPrinter(NULL, &bufSize);
        if(!result)
        {
            err = GetLastError();
            if (ERROR_INSUFFICIENT_BUFFER != err)
            {
                std::cout << "GetDefaultPrinter failed with error: \n" << GetLastError();
                return 0;
            }
        }
    
        buf = (WCHAR*)calloc(bufSize, sizeof(WCHAR));
        result = GetDefaultPrinter(buf, &bufSize);
        if (!result)
        {
            std::cout << "GetDefaultPrinter failed with error: \n" << GetLastError();
            return 0;
        }
        std::wcout << "Printer name: " << buf << "\n";
        result = OpenPrinter(buf, &hPrinter, NULL);
        if (!result)
        {
            std::cout << "OpenPrinter failed with error: \n" << GetLastError();
            return 0;
        }
    
        result = GetPrinter(hPrinter, 6, (LPBYTE)&info, sizeof(PRINTER_INFO_6), &needed);
        if (!result)
        {
            err = GetLastError();
            if (ERROR_INSUFFICIENT_BUFFER != err)
            {
                std::cout << "GetPrinter failed with error: \n" << GetLastError();
                return 0;
            }
        }
    
        BYTE* statBuf = (BYTE*)calloc(needed, sizeof(BYTE));
        result = GetPrinter(hPrinter, 6, statBuf, needed, &needed);
        if (!result)
        {
            std::cout << "GetPrinter failed with error: \n" << GetLastError();
            return 0;
        }
    
        std::cout << "Printer status (low 32bit): " << *((DWORD*)statBuf) << "\n";
        statBuf += sizeof(DWORD);
        std::cout << "Printer status (high 32bit): " << *((DWORD*)statBuf) << "\n";
    
        getchar();
    }
    

    Some issues I found in testing:

    1. Pinter status defined as a DWORD (4 bytes) in PRINTER_INFO_6 structure but GetPrinter requries 8 bytes for it (needed == 8). So you will get ERROR_INSUFFICIENT_BUFFER error when you pass a PRINTER_INFO_6 structure as pPrinter parameter.
    2. There is only PRINTER_INFO_6 defined but no _PRINTER_INFO_6W (Unicode) and _PRINTER_INFO_6A (ANSI) mentioned in the document.