原始打印直接到 USB 打印机,绕过 Windows 后台处理程序 [英] Raw printing directly to a USB printer, bypassing Windows spooler

查看:72
本文介绍了原始打印直接到 USB 打印机,绕过 Windows 后台处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试用 Zebra TTP8200 热敏打印机.对于我的应用程序,我需要连续打印绘图仪类型的轨迹,直到用户点击停止按钮.我玩过 ZPL 语言,我可以成功生成位图数据,并通过将 ZPL 作为原始数据输出,一次将我的位图输出一行(或几行).

I'm experimenting with a Zebra TTP8200 thermal printer. For my application I need to print plotter type traces continuously until the user hits a stop button. I've had a play with the ZPL language and I can successfully generate bitmap data and dump out my bitmap a line (or few lines) at a time by outputting the ZPL as raw data.

我正在使用一些 Microsoft 演示代码 将原始数据输出到打印机,这很有效,只有一个问题:假脱机程序.事实证明,每次我使用 MS rawprn.exe 代码输出一些数据时,它实际上都被假脱机作为打印作业,然后传输到打印机.这最多需要 10 秒才能通过假脱机程序,显然太慢了.在驱动程序中禁用假脱机没有帮助,这只是意味着程序在作业通过假脱机程序和打印完成时挂起.

I'm using some Microsoft demo code to output the raw data to the printer and this works great, bar one issue: the spooler. It turns out that every time I output some data using the MS rawprn.exe code it is actually spooled as a print job and then transmitted to the printer. This takes up to 10 seconds to get through the spooler, obviously too slow. Disabling spooling in the driver doesn't help, it just means that the program hangs while the job is passed through the spooler and printing completes.

有没有办法绕过假脱机程序并将数据直接输出到这台 USB 打印机?到目前为止,我的研究还没有发现任何可能在 Windows API 中寻找的东西.理想情况下,我希望能够像使用串行打印机一样使用打印机 - 打开端口并输入数据.

Is there a way to bypass the spooler and output data straight to this USB printer? My research so far hasn't turned up anything likely looking in the Windows API. Ideally, I'd like to be able to use the printer like it was a serial printer - open the port and shove data in.

非常感谢您提供任何提示!

Many thanks in advance for any hints!

推荐答案

感谢您的评论.

经过更多的挖掘,我发现了这篇关于使用 usbprint.sys 提供的 Windows 打印机功能的有趣文章.通过对示例代码进行一些破解,似乎可以正常工作.我想我会走这条路.

After some more digging around, I found this interesting article on using Windows printer functions provided by usbprint.sys. With a bit of hacking the sample code there seemed to work. I think I'll take this route.

有文章中给出的最终代码:

There is the final code given in the article:

/* Code to find the device path for a usbprint.sys controlled
* usb printer and print to it
*/

#include <usb.h>
#include <usbiodef.h>
#include <usbioctl.h>
#include <usbprint.h>
#include <setupapi.h>
#include <devguid.h>
#include <wdmguid.h>

/* This define is required so that the GUID_DEVINTERFACE_USBPRINT variable is
 * declared an initialised as a static locally, since windows does not include it
 * in any of its libraries
 */

#define SS_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
static const GUID name \
= { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

SS_DEFINE_GUID(GUID_DEVINTERFACE_USBPRINT, 0x28d78fad, 0x5a12, 0x11D1, 0xae,
               0x5b, 0x00, 0x00, 0xf8, 0x03, 0xa8, 0xc2);

void SomeFunctionToWriteToUSB()
{
  HDEVINFO devs;
  DWORD devcount;
  SP_DEVINFO_DATA devinfo;
  SP_DEVICE_INTERFACE_DATA devinterface;
  DWORD size;
  GUID intfce;
  PSP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;

  intfce = GUID_DEVINTERFACE_USBPRINT;
  devs = SetupDiGetClassDevs(&intfce, 0, 0, DIGCF_PRESENT |
                             DIGCF_DEVICEINTERFACE);
  if (devs == INVALID_HANDLE_VALUE) {
    return;
  }
  devcount = 0;
  devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  while (SetupDiEnumDeviceInterfaces(devs, 0, &intfce, devcount, &devinterface)) {
    /* The following buffers would normally be malloced to he correct size
     * but here we just declare them as large stack variables
     * to make the code more readable
     */
    char driverkey[2048];
    char interfacename[2048];
    char location[2048];
    char description[2048];

    /* If this is not the device we want, we would normally continue onto the
     * next one or so something like
     * if (!required_device) continue; would be added here
     */
    devcount++;
    size = 0;
    /* See how large a buffer we require for the device interface details */
    SetupDiGetDeviceInterfaceDetail(devs, &devinterface, 0, 0, &size, 0);
    devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
    interface_detail = calloc(1, size);
    if (interface_detail) {
      interface_detail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
      devinfo.cbSize = sizeof(SP_DEVINFO_DATA);
      if (!SetupDiGetDeviceInterfaceDetail(devs, &devinterface, interface_detail,
                                           size, 0, &devinfo)) {
    free(interface_detail);
    SetupDiDestroyDeviceInfoList(devs);
    return;
      }
      /* Make a copy of the device path for later use */
      strcpy(interfacename, interface_detail->DevicePath);
      free(interface_detail);
      /* And now fetch some useful registry entries */
      size = sizeof(driverkey);
      driverkey[0] = 0;
      if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo, SPDRP_DRIVER, &dataType,
                                            (LPBYTE)driverkey, size, 0)) {
    SetupDiDestroyDeviceInfoList(devs);
    return;
      }
      size = sizeof(location);
      location[0] = 0;
      if (!SetupDiGetDeviceRegistryProperty(devs, &devinfo,
                                            SPDRP_LOCATION_INFORMATION, &dataType,
                                            (LPBYTE)location, size, 0)) {
    SetupDiDestroyDeviceInfoList(devs);
    return;
      }
      usbHandle = CreateFile(interfacename, GENERIC_WRITE, FILE_SHARE_READ,
                 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL |
                 FILE_FLAG_SEQUENTIAL_SCAN, NULL);
      if (usbHandle != INVALID_HANDLE_VALUE) {
    /* Now perform all the writing to the device ie.
     * while (some condition) WriteFile(usbHandle, buf, size, &bytes_written);
     */
    CloseHandle(usbHandle);
      }
    }
  }
  SetupDiDestroyDeviceInfoList(devs);
}

再次感谢您的建议.

这篇关于原始打印直接到 USB 打印机,绕过 Windows 后台处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆