使用 ReadPrinter 读取打印机数据 Winspool.Drv

Reading printer data using ReadPrinter Winspool.Drv

我通过 USB 连接了 Zebra 打印机,我正在尝试使用命令 ^XA^HWR:^XZ 读取打印机的内存。该命令适用于 TCP/IP。

我什至不确定我的方法header是否正确。

[DllImport("winspool.Drv", EntryPoint = "ReadPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
static extern bool ReadPrinter(IntPtr hPrinter, IntPtr pBuf, int cbBuf, out int pNoBytesRead);

方法ReadPrinter总是returns false 和 0 个读取字节。当我尝试获取 LastWin32Error 时,我得到的是各种 0、6 或 63(ERROR_SUCCESS - 尽管它 returns 为假且没有数据,ERROR_INVALID_HANDLEERROR_PRINT_CANCELLED),这取决于我正在尝试的。我尝试了几种方法 headers 和不同的方法,但其中 none 导致成功读取数据。我启用了 'bidirectional support' 并安装了打印机驱动程序。它可能看起来像其他线程的副本,但我已经通过它们并且 none 其中有帮助。

代码片段:

    private static void SendBytesToPrinter(string printerName, IntPtr pointerBytes, int bytesCount)
    {
        int written = 0;
        PrintResult printResult = new PrintResult();
        IntPtr pointerPrinter = new IntPtr(0);
        DOCINFOA docInfo = new DOCINFOA();
        bool success = false;

        docInfo.DocName = "RAW Document";
        docInfo.DataType = "RAW";

        try
        {
            if (OpenPrinter(printerName.Normalize(), out pointerPrinter, IntPtr.Zero))
            {
                if (StartDocPrinter(pointerPrinter, 1, docInfo))
                {
                    if (StartPagePrinter(pointerPrinter))
                    {
                        success = WritePrinter(pointerPrinter, pointerBytes, bytesCount, out written);
                        EndPagePrinter(pointerPrinter);
                    }

                    EndDocPrinter(pointerPrinter);
                 }

                 // READ HERE
                 Int32 bufLen = 32;
                 IntPtr pStatus = Marshal.AllocCoTaskMem(bufLen);
                 Int32 statusLen = 0;
                 bool bSuccess = ReadPrinter(hPrintJob, pStatus, bufLen, out statusLen);

                 ClosePrinter(pointerPrinter);
             } 
        } catch (Exception ex) { }
    }

我使用 Visual Basic 示例解决了它,使用 FileStreamsStreamReaders。感谢@kunif 指出示例代码。

kernel32.dll 是代替 winspool.Drv

的方法
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern SafeFileHandle CreateFile(string lpFileName, EFileAccess dwDesiredAccess, 
                                                EFileShare dwShareMode, IntPtr lpSecurityAttributes, 
                                                ECreationDisposition dwCreationDisposition, 
                                                EFileAttributes dwFlagsAndAttributes, 
                                                IntPtr hTemplateFile);

private static string ReadUsbPort(StreamReader sr)
{
    string readResult = string.Empty;
    if (sr != null && sr.BaseStream != null)
    {
       do
       {
            readResult += sr.ReadLine();
            readResult += "\r";
        }
        while (sr.EndOfStream == false);
     }
   return readResult;
}

非常有用的组合 GUID_DEVINTERFACE_USB_DEVICE and WinUSBNet