无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
查看: 30238|回复: 314
打印 上一主题 下一主题

[求助] 刚刚在论坛看到一个共享打印机的好东西raw print server

  [复制链接]
1#
发表于 2022-9-4 18:17:58 | 显示全部楼层
找到一个类似的东西,在家没测试环境,也不知道和lz提供的是不是差不多的东西
https://github.com/frogmorecs/RawPrint/tree/master/RawPrint
回复

使用道具 举报

2#
发表于 2022-9-4 21:52:46 | 显示全部楼层
chinaren12 发表于 2022-9-4 20:10
这个是单机使用的,不能网络,我也搜到了这个工具,这个rawprint主要是供单机的。没有网络打印功能。

我试着修改了一下,不知道能不能用,
你试试

RawPrintServer.rar

17.97 KB, 下载次数: 124, 下载积分: 无忧币 -2

回复

使用道具 举报

3#
发表于 2022-9-5 11:56:06 | 显示全部楼层
357734620 发表于 2022-9-5 11:15
测试不成功啊。
1.客户机能正常发送【打印测试页】到服务器上,服务器打印列表里显示文档名为:Forwarded  ...

请提供详细的系统版本信息,打印机型号信息,网络信息等,
出错貌似会生成日志,不知道你找得到不
回复

使用道具 举报

4#
发表于 2022-9-5 20:30:34 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-5 20:34 编辑
chinaren12 发表于 2022-9-5 14:17
我刚刚用实机测试了一下,似乎不行,不知道是哪个搞错了。
我弄了一台笔记本,然后装了个hp p1007的打印 ...

我修改的源代码见附件,
就是改了一行加入了获取文件路径,原作者写的相对路径,
然后具体不能用,请查看"C:\\PrintServer.log"
看看错误信息是什么

其中有一条,就是你安装设置的这个名称要和你机器上打印机名字一模一样
char *printerName = "Test;//"Brother HL-1430 series";

其他就是OpenPrinter和StartDocPrinter以及WritePrinter了,
另外有篇文章说https://www.cnblogs.com/lobsterIT/p/4610504.html
https://blog.csdn.net/kingmax54212008/article/details/8985965
请继续测试

RawPrintServer100beta1-修改后源码.rar

12.93 KB, 下载次数: 36, 下载积分: 无忧币 -2

回复

使用道具 举报

5#
发表于 2022-9-5 20:41:05 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-5 20:42 编辑
yxc51 发表于 2022-9-5 20:37
我遇到同样的问题:服务端是win7系统,安装了一台联想M7250n的网络打印机,用rawprintsever install "M72 ...

请查看"C:\\PrintServer.log"看看错误信息是什么
参考https://docs.microsoft.com/zh-cn ... g-the-gdi-print-api有句话说 打印通常是本机Windows程序不可或缺的一部分,因此在编写程序后,无法轻松添加该功能。 设计 Windows 7 的程序时,应考虑使用 XPS 打印 API 提供打印功能,因为它为将来提供最兼容性。 必须在 Windows Vista 和早期版本的 Windows 上运行的程序最有可能使用 GDI 打印 API 提供打印功能。 Windows 7 也支持 GDI 打印 API,但它比 XPS 打印 API 更有限。
回复

使用道具 举报

6#
发表于 2022-9-5 20:43:42 | 显示全部楼层
还有https://docs.microsoft.com/zh-cn ... ocs/startdocprinter也提到:当后台处理程序文件中的页面超过大约 350 MB 时,它可能无法打印,并且无法发送错误消息。 例如,打印大型 EMF 文件时可能会发生这种情况。 页面大小限制取决于许多因素,包括可用的虚拟内存量、通过调用进程分配的内存量以及进程堆中的碎片量。   以及  这是阻塞或同步函数,可能不会立即返回。 此函数的返回速度取决于运行时因素,例如网络状态、打印服务器配置和打印机驱动程序实现因素,在编写应用程序时难以预测。 从管理与用户界面交互的线程调用此函数可能会使应用程序看起来无响应。
回复

使用道具 举报

7#
发表于 2022-9-5 20:59:05 | 显示全部楼层
yxc51 发表于 2022-9-5 20:37
我遇到同样的问题:服务端是win7系统,安装了一台联想M7250n的网络打印机,用rawprintsever install "M72 ...

https://docs.microsoft.com/zh-cn ... mode-pcl-postscript这儿说
V4 驱动程序是基于 XPS 的驱动程序。 RAW 数据库不兼容。 将 v3 XPS 打印机驱动程序与 Vista 或 (7) 一Windows V3 XPS 打印机驱动程序Windows类似。
Datatype 是在 Vista Windows引入的,用于将 XPS 直接传递到 XPS_PASS v3 XPSDrv 驱动程序的打印筛选器管道。 这可以防止 RAW v3 驱动程序的数据类型过载。 XPS_PASS 已 RAW 替换为 v4 驱动程序
大概意思是vista之后某个类型改了,之前的不能用,
我又改了一个版本,你再试试能不能用,源代码里面也包含了,
有问题继续提交日志C:\\PrintServer.log上来

RawPrintServer100beta1-XPS.rar

31.26 KB, 下载次数: 30, 下载积分: 无忧币 -2

回复

使用道具 举报

8#
发表于 2022-9-5 21:04:40 | 显示全部楼层
chinaren12 发表于 2022-9-5 20:59
感谢兄弟的付出,我稍后试试再反馈给你
  1. //
  2. //  RawDataToXpsPrinter - sends binary data directly to a printer
  3. //          with an XPSDrv Printer Driver
  4. //  
  5. // szPrinterName: NULL-terminated string specifying printer name
  6. // lpData:        Pointer to raw data bytes
  7. // dwCount        Length of lpData in bytes
  8. //  
  9. // Returns: TRUE for success, FALSE for failure.
  10. //  
  11. BOOL RawDataToXpsPrinter (LPTSTR szPrinterName, LPBYTE lpData, DWORD dwCount)
  12. {
  13.     BOOL     bStatus = FALSE;
  14.     HANDLE     hPrinter = NULL;
  15.     DOC_INFO_1       DocInfo;
  16.     DWORD    dwPrtJob = 0L;
  17.     DWORD    dwBytesWritten = 0L;

  18.     // Open a handle to the printer.
  19.     bStatus = OpenPrinter (szPrinterName, &hPrinter, NULL);
  20.    
  21.     if (bStatus) {
  22.         // Fill in the structure with info about this "document."
  23.         DocInfo.pDocName = (LPTSTR)_T("My Document");
  24.         DocInfo.pOutputFile = NULL;

  25.         // Enter the datatype of this buffer.
  26.         //  Use "XPS_PASS" when the data buffer should bypass the
  27.         //    print filter pipeline of the XPSDrv printer driver.
  28.         //    This datatype would be used to send the buffer directly
  29.         //    to the printer, such as when sending print head alignment
  30.         //    commands. Normally, a data buffer would be sent as the
  31.         //    "RAW" datatype.
  32.         //
  33.         DocInfo.pDatatype = (LPTSTR)_T("XPS_PASS");

  34.         dwPrtJob = StartDocPrinter (
  35.                         hPrinter,
  36.                         1,
  37.                         (LPBYTE)&DocInfo);

  38.         if (dwPrtJob > 0) {
  39.                 // Send the data to the printer.
  40.                 bStatus = WritePrinter (
  41.                 hPrinter,
  42.                 lpData,
  43.                 dwCount,
  44.                 &dwBytesWritten);
  45.         }
  46.         
  47.         EndDocPrinter (hPrinter);

  48.         // Close the printer handle.
  49.         bStatus = ClosePrinter(hPrinter);
  50.     }
  51.    
  52.     if (!bStatus || (dwCount != dwBytesWritten)) {
  53.         bStatus = FALSE;
  54.     } else {
  55.         bStatus = TRUE;
  56.     }

  57.     return bStatus;
  58. }
复制代码
上述代码来自https://docs.microsoft.com/zh-cn ... y-to-an-xps-printer
大概意思是vista之后使用了新的XPS驱动来操作打印机,
之前的GDI驱动已经支持有限了还是怎么的,说不定就是不支持了说的比较隐晦,
回复

使用道具 举报

9#
发表于 2022-9-6 11:46:29 | 显示全部楼层
chinaren12 发表于 2022-9-6 09:11
使用xps版也不行。

下面是错误提示

增加如下代码,把错误信息输出到log,看看错误到底是什么,
  1.     if (!OpenPrinter(printerName, &printer, NULL) )
  2.                                 {
  3.                                         WriteToLog("Error OpenPrinter.");
  4.                                         //printf("OpenPrinter GetLastError %d \n",GetLastError());
  5.                                         sprintf(strerr,"OpenPrinter GetLastError %d \n",GetLastError());
  6.                                         WriteToLog(strerr);

  7.                                 }       
  8.                                

  9.                                 if( !StartDocPrinter(printer, 1, (LPBYTE)&info))
  10.                                 {
  11.                                         WriteToLog("Error StartDocPrinter.");
  12.                                         //printf("StartDocPrinter GetLastError %d ",GetLastError());
  13.                                         sprintf(strerr,"StartDocPrinter GetLastError %d \n",GetLastError());
  14.                                         WriteToLog(strerr);
  15.                                 }
复制代码



RawPrintServer100beta1-20220906.rar

31.48 KB, 下载次数: 20, 下载积分: 无忧币 -2

回复

使用道具 举报

10#
发表于 2022-9-6 20:29:33 | 显示全部楼层
yxc51 发表于 2022-9-6 15:13
兄弟和我测试结果一样啊。

又修改了一下
增加如下
  1.       bStatus=WritePrinter(printer, buffer, result, &wrote);
  2.                                                 if (bStatus)
  3.                                                 {
  4.                                                                 WriteToLog("WritePrinter error.");

  5.                                                 }
复制代码
看看错误在哪里

RawPrintServer100beta1.rar

31.71 KB, 下载次数: 9, 下载积分: 无忧币 -2

回复

使用道具 举报

11#
发表于 2022-9-6 22:28:42 | 显示全部楼层
chinaren12 发表于 2022-9-6 20:51
感谢兄弟的坚持。

明日再测试反馈结果给你,谢谢了。

又更新了一下,增加输出getlasterror功能
但我拿adobe pdf打印机测试
能发送打印任务,没错误返回,
但pdf打印机没反应,
日志如下,
PrintServer start
Accept print job for Adobe PDF from 10.232.28.12

搜了一下发现网络上也有人说代码运行正常,但打印机没反应的,
但也有人说成功,问题在哪里呢

RawPrintServer100beta1.rar

31.69 KB, 下载次数: 5, 下载积分: 无忧币 -2

回复

使用道具 举报

12#
发表于 2022-9-7 09:48:33 | 显示全部楼层
chinaren12 发表于 2022-9-7 09:09
这个1.0的正式版也不行,不知道是不是不兼容HP的打印机呢?还是如你所说的那样需要通用打印驱动 ...

找到一篇文章,
通过添加端口设置 generic厂家的text only驱动来打开raw模式支持,
你试试

How to configure RAW printing mode in Windows.pdf

206.74 KB, 下载次数: 28, 下载积分: 无忧币 -2

回复

使用道具 举报

13#
发表于 2022-9-7 10:55:07 | 显示全部楼层
yxc51 发表于 2022-9-7 09:52
感谢兄弟锲而不舍的努力。下了群友说的正式版的测试打印成功,兄弟可研究一下这个正式版的源码,进行改进 ...

正式版和测试版区别只有一个地方,就是下图,
测试版接受数据完成就返回了,正式版还会继续执行ClosePrinter关闭打印机,
不过在我这测试,打印机还是没反应,不知道为啥
附件是修改了获取本文件路径的代码,请再试试

代码区别.png (82.81 KB, 下载次数: 54)

代码区别.png

RawPrintServer100.rar

49.48 KB, 下载次数: 87, 下载积分: 无忧币 -2

回复

使用道具 举报

14#
发表于 2022-9-7 12:07:06 | 显示全部楼层
chinaren12 发表于 2022-9-7 11:18
我去,为什么我不能成功呢?你什么打印机型号

我测试HP LaserJet P1007也没反应,不知道哪里有问题
回复

使用道具 举报

15#
发表于 2022-9-7 22:39:59 | 显示全部楼层
chinaren12 发表于 2022-9-7 22:23
这软件方案如果能完善的话,也不失为一种很好的替代方法呀。。。

我搜索一下是有人反映能用也有人说不能用,
可能真和打印机型号或者驱动有关系,
利用路由器usb口接打印机的方法我也知道,
但好些公司不允许个人接路由器到公司内网
回复

使用道具 举报

16#
发表于 2022-9-8 10:29:48 | 显示全部楼层
chinaren12 发表于 2022-9-7 22:55
是的,打印服务器我有很多种,但总有碰到不想花钱的人的。这时候就可以派上用场了。

我从MS网站上找了一段代码,
随便打开一个文件,选择hp1007打印机,打印到文件,之后保存为test1,
再用这个程序输出到打印机,正常打印出来了
我怀疑是不是网络传输问题
测试程序和源码我都放附件了你看看,
命令是print "HP LaserJet P1007" test1

测试打印成功.png (9.61 KB, 下载次数: 69)

测试打印成功.png

print.rar

24.61 KB, 下载次数: 15, 下载积分: 无忧币 -2

回复

使用道具 举报

17#
发表于 2022-9-8 11:54:47 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-8 11:56 编辑
chinaren12 发表于 2022-9-7 14:03
老哥,我晚点测试后给你回信。。。
仔细测试发现WritePrint代码其实没问题,是发过去的数据打印机不认识,某些比较老的打印机支持的格式很少
使用Port Monitor工具,监听9100端口发过来的内容,
对于P1007打印机,
如果是如下这种XQX开头的PS格式,有可能可以打印,
某些比较新的打印机甚至可以直接接受PDF格式输入

XQX.png (77.28 KB, 下载次数: 62)

XQX.png
回复

使用道具 举报

18#
发表于 2022-9-8 15:14:32 | 显示全部楼层
chinaren12 发表于 2022-9-8 14:20
所以,能否添加支持HP打印机的代码?老哥。。。。

参考https://t2.re/archives/708/
https://www.right.com.cn/forum/f ... d&tid=212810&page=1
以及https://oldwiki.archive.openwrt.org/doc/howto/p910nd.server
https://plugout.net/viewtopic.php?f=12&t=2161&start=10

发现HP 1000 1005 1018 1020打印机这一系列,需要先给打印机发一个文件
让打印机进工作状态,才能开始打印
能够打印的关键步骤:cat /usr/lib/sihpP1007.dl > /dev/usb/lp0, 就是要把固件上传到打印机才行
手动执行是nc -q2 192.168.2.99 9100 < /usr/share/foo2zjs/firmware/sihp1020.dl
根据不同的型号发sihp1020.dl或者sihpP1007.dl
然后打印机设置禁用双向模式
  1. FIRMWARE="/usr/lib/sihp1020.dl"  (replace with the real path)
  2. DEVICE=/dev/lp0
  3. LOGFILE=/var/log/hp

  4. for i in $(seq 30); do
  5.      if [ -c $DEVICE ]; then
  6.             /bin/echo "$(date) : Sending firmware to printer." > $LOGFILE
  7.             /bin/cat $FIRMWARE > $DEVICE
  8.             /bin/echo "$(date) : done." >> $LOGFILE
  9.              exit
  10.       fi
  11.       sleep 1
  12. done
复制代码
上面这个是使用路由器USB连接,每次打印要先发sihpP1007.dl过去

sihp1007-1020.rar

207.66 KB, 下载次数: 3, 下载积分: 无忧币 -2

回复

使用道具 举报

19#
发表于 2022-9-8 15:18:55 | 显示全部楼层
昨天就基本搞定了,不会咔哒咔哒响了,也不会重复打印了,而且打印任务也能正常停止,也没有用到usb_printerid(需要交叉编译),但是不太稳定的地方是:有时打印任务出不来,打印测试页每次都OK,但是有时word和Excel的任务出不来。
关键步骤就是:在Windows中去掉“双向打印”的对勾即可。

考虑到目前对于共享打印的诉求不是太强烈,暂时放弃了。以后有机会再试试CUPS,不过好像OpenWRT官方停止对CUPS的支持了。



我把用到的脚本贴上来,供大家参考一下,强烈建议大家仔细看原帖的内容,这些脚本都是从那儿COPY过来修改的:

/etc/config/p910nd, 是不需要修改的!

/etc/hotplug.d/usb/10-printer

#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
if [ "$PRODUCT" ="3f0/4817/100" ]
then
case "$ACTION" in
        add)
        /etc/init.d/p910nd stop
        echo "`date`: HP LaserJet P1007 added" >> /tmp/hp-1007
        /etc/init.d/p910nd start >> /tmp/hp-1007
        echo "Done." >> /tmp/hp-1007
        ;;
        remove)
        echo "`date`: HP LaserJet P1007 removed" >> /tmp/hp-1007
        /etc/init.d/p910nd stop >> /tmp/hp-1007
        echo "Done." >> /tmp/hp-1007
        ;;
esac
fi

上述命令成功了,插拔打印机之后,有反应。

/etc/hotplug.d/usb/10-hplj1007

#!/bin/sh

set -e

# change this to the location where you put the .dl file:
FIRMWARE="/usr/lib/sihpP1007.dl"
DEVICE=/dev/usb/lp0
LOGFILE=/tmp/hp-fm

if [ "$PRODUCT" = "3f0/4817/100" -a "$ACTION" = "add" ]; then
        for i in $(seq 30); do
                if [ -c $DEVICE ]; then
                        echo "$(date) : Sending firmware to printer…" > $LOGFILE
                        cat $FIRMWARE > $DEVICE
                        echo "$(date) : done." » $LOGFILE
                        exit
                fi
                sleep 1
        done
fi

上述脚本也可以用,但是同样会不停的打印,而且打印任务也无法结束。

针对HP的GDI系列,应该改为下列的样子

#!/bin/sh

set -e

# change this to the location where you put the .dl file:
FIRMWARE=/usr/lib/sihpP1007.dl
DEVICE=/dev/usb/lp0
LOGFILE=/tmp/hp-fm

if [ "$PRODUCT" = "3f0/4817/100" -a "$ACTION" = "add" -a "$DEVTYPE" = "usb_interface" ]; then
   echo "$(date): STARTING" > $LOGFILE
   for i in $(seq 30); do
       echo "$(date): Attempt number $i on $DEVICE" » $LOGFILE
       if [ -c $DEVICE ]; then
          echo "$(date): Device $DEVICE found." » $LOGFILE
          if [ -z "`usb_printerid $DEVICE | grep FWVER`" ]; then
              echo "$(date): No firmware found on $DEVICE" » $LOGFILE
              echo "$(date): Sending firmware to printer…" » $LOGFILE
              cat $FIRMWARE > $DEVICE
              echo "$(date): done." » $LOGFILE
          else
              echo "$(date): Firmware already there on $DEVICE" » $LOGFILE
          fi
          echo "$(date): EXITING" » $LOGFILE
          exit
       fi
       sleep 1
    done
fi
上面是连接路由器的代码,先保存到论坛上,再看看怎么改造一下给win使用

回复

使用道具 举报

20#
发表于 2022-9-8 15:39:58 | 显示全部楼层
Climbing 发表于 2022-9-8 13:30
大家都知道Windows的打印共享一直属于玄学,2000/XP/2003(NT 5.x)及以前的时代基本还算正常,经过简单 ...

版主可以试试我修改的版本,在本帖子88楼
不需要手动设置ImagePath了,自动获取,
源代码也在里面,可以修改日志位置
回复

使用道具 举报

21#
发表于 2022-9-8 17:15:35 | 显示全部楼层
chinaren12 发表于 2022-9-8 14:20
所以,能否添加支持HP打印机的代码?老哥。。。。

测试发现问题出在发送的机器这边,
首先在本机选择p1007打印到文件,保存为test1,
然后执行 nc 192.168.1.2 9100 <test1
过几秒钟按ctrl-c结束nc,
打印机就开始工作了,打印出来了,
日志如下
RawPrintServer 1.00 created by Henk Jonas (www.metaviewsoft.de)
PrintServer start
HP LaserJet P1007 on 9100 (9100)
Accept print job for HP LaserJet P1007 from 192.168.1.12
PrintServer stopped.
PrintServer exit

test1.rar

787 Bytes, 下载次数: 2, 下载积分: 无忧币 -2

回复

使用道具 举报

22#
发表于 2022-9-8 17:42:42 | 显示全部楼层
搜索了一下大概是P1007是比较老的打印机,
不支持比较新的打印格式,只能打GDI格式,
新系统比如win10可能配置网络打印机之后,发出去的格式已经是新格式了,
P1007打印机收到了,但不能识别,
我也测试了先执行nc 192.168.1.2 9100 <sihpP1007.dl
再打印,P1007打印机还是没反应
回复

使用道具 举报

23#
发表于 2022-9-8 17:52:19 | 显示全部楼层
chinaren12 发表于 2022-9-8 14:20
所以,能否添加支持HP打印机的代码?老哥。。。。

翻了不少资料大概理解了打印机工作过程,
资料说WritePrint会不经过驱动程序直接发送文件给打印机
打个比方吧,有甲乙丙三个人,甲是翻译,乙是快递员,丙是打字员,
我们把PDF文件交给甲,
甲会翻译成GDI格式让乙去送,乙会检查是本地打印机还是远程打印机
然后送到丙那里,丙把GDI文件写纸上。

某些新打印机,我们直接给丙送PDF他也可以写,
但老打印机不识别,这估计就是打印机有准备动作但不打印的原因

支持HP打印机有两种思路
1.自行配置打印到文件,然后使用nc或其他工具把文件送到raw print,
上面实测可以用,就是得手动操作
2.想办法让打印机识别新的格式,
路由器接USB那种,发一个dl文件给打印机,再发真正要打印的东西出去,
我使用nc直接发出去还不行,可能还要改什么东西

回复

使用道具 举报

24#
发表于 2022-9-9 10:42:09 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-9 10:43 编辑
chinaren12 发表于 2022-9-8 19:55
极有可能,hp的m1005,p1007,p1008,p1108等打印机的打印处理器都不是winprint的raw。。。

这可能就 ...

继续修改,参考路由器实现方法,
先发一段数据给打印机,再开始打印
数据已经被我写的程序里面如下
unsigned char data[222443]
这个应该只能用于p1007,请试试,hp1xxx系列估计都要发这个给打印机
来源是https://dl.t2.re/Others/Openwrt% ... 3%E5%8D%B0%E6%9C%BA


hp打印机.png (45.37 KB, 下载次数: 62)

hp打印机.png

RawPrintServer100-p1007.rar

626.8 KB, 下载次数: 51, 下载积分: 无忧币 -2

回复

使用道具 举报

25#
发表于 2022-9-10 22:32:27 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-10 22:36 编辑
chinaren12 发表于 2022-9-10 12:26
我下午看看,这个好像比rawprintserver更全面。
但是我没看明白这个怎么使用的。

这个我在本贴25楼已经发过了,
Send PostScript, PCL or other print file types directly to a printer.
大概功能和我104楼提供那个print测试差不多,
直接发送PS或者PCL格式给打印机,问题是p1007只认RAW格式,其他打印机支持这些格式可以直接打
回复

使用道具 举报

26#
发表于 2022-9-11 20:33:42 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-11 20:43 编辑
chinaren12 发表于 2022-9-11 11:06
P1007可以打印了。打印测试页也可以,可以直接打印文档。
接近完美了。你可以把另外的HP打印机型号加进 ...

感谢大神耐心测试,真是好消息
我测试发给p1007打印机一个任务,任务没自动消失,
但打印机也没反应,我就取消了打印任务,
不知道是不是p1007反应比较慢,还是我发送端配置有问题,
我的配置如下,请大神指点

端口9100.png (26.46 KB, 下载次数: 65)

端口9100.png

p1007.png (45.17 KB, 下载次数: 58)

p1007.png

处理器.png (21.18 KB, 下载次数: 61)

处理器.png

高级.png (102.15 KB, 下载次数: 52)

高级.png
回复

使用道具 举报

27#
发表于 2022-9-11 20:54:01 | 显示全部楼层
chinaren12 发表于 2022-9-11 19:05
如果把这些1006,1007,1008,1505,1005都写到这个小工具里面,那你要如何判断对应的打印机是什么型号呢 ...

一般来说,大部分人不会改打印机的名字,
判断名字基本上可行
最严谨的方法肯定判断USB对应的PID和VID,
设备就靠PID和VID来识别和安装驱动的,
还有个最简单粗暴的方法,就是让用户选择,

也就是增加一个hp参数,属于余下打印机的多加个-hp1000让rawprint识别
hp1000
hp1005
hp1018
hp1020
hpP1005
hpP1006
hpP1007
hpP1008
hpP1505
回复

使用道具 举报

28#
发表于 2022-9-11 22:36:25 | 显示全部楼层
本帖最后由 zhuwg 于 2022-9-11 22:37 编辑
chinaren12 发表于 2022-9-11 21:15
我觉得还是用打印机名字吧!毕竟通过pid和vid可能会加大难度和工作量。

我随便找了一段代码,实测可以正常获取pid和gid,
但有个问题,如果安装了超过一台打印机看怎么识别
  1. // usb.cpp : Defines the entry point for the console application.
  2. //

  3. #include "stdafx.h"

  4. #include <windows.h>
  5. #include <cstdio>
  6. #include <iostream>
  7. #include <algorithm>
  8. #include <vector>
  9. #include <atlstr.h>
  10. #include <strmif.h>
  11. #include <setupapi.h>
  12. #include <initguid.h>
  13. #pragma comment(lib,"setupapi.lib")
  14. #pragma comment(lib,"strmiids.lib")
  15. using namespace std;

  16. DEFINE_GUID(CLSID_SystemDeviceEnum, 0x62be5d10, 0x60eb, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
  17. DEFINE_GUID(GUID_DEVINTERFACE_HID, 0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);

  18. //存放设备的PID VID DEVID信息;
  19. typedef struct _DevInfo
  20. {
  21.         int nPID;
  22.         int nVID;
  23.         int nDevId;
  24. }DevInfo, * pDevInfo;

  25. std::vector<DevInfo> vecDevInfo;
  26. //获取所有设备的PID_VID Begin


  27. HRESULT EnumAllDevices()
  28. {        
  29.         int nRet = -1;
  30.         // 初始化当前线程上的COM库
  31.         CoInitialize(NULL);
  32.         ICreateDevEnum* pDevEnum = NULL;
  33.         // 创建与指定的类标识符关联的类的单个未初始化对象。
  34.         HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, // 用于创建对象的数据和代码关联的类标识符
  35.                 NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (LPVOID*)&pDevEnum);
  36.         if (SUCCEEDED(hr))
  37.         {
  38.                 IEnumMoniker* pEnumMon = NULL;
  39.                 hr = pDevEnum->CreateClassEnumerator(GUID_DEVINTERFACE_HID, &pEnumMon, 0);
  40.                 if (hr == S_OK)
  41.                 {
  42.                         pEnumMon->Reset();
  43.                         ULONG cFetched = 0;
  44.                         IMoniker* pMoniker = NULL;
  45.                         while (hr = pEnumMon->Next(1, &pMoniker, &cFetched), hr == S_OK)
  46.                         {
  47.                                 IPropertyBag* pProBag = NULL;
  48.                                 hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (LPVOID*)&pProBag);
  49.                                 if (SUCCEEDED(hr))
  50.                                 {
  51.                                         OLECHAR* pName = NULL;
  52.                                         hr = pMoniker->GetDisplayName(NULL, NULL, &pName);
  53.                                         if (SUCCEEDED(hr))
  54.                                         {
  55.                                                 CString szTemp;
  56.                                                 BSTR bsTemp = SysAllocString(pName); // 分配内存
  57.                                                 szTemp = bsTemp;
  58.                                                 SysFreeString(bsTemp);
  59.                                                 pName = NULL;
  60.                                                 //解析字符串
  61.                                                 szTemp.Delete(0, szTemp.Find(_T("#")) + 1);
  62.                                                 szTemp.Delete(szTemp.Find(_T("#")), 1000);
  63.                                                 szTemp.Delete(17, 1000);
  64.                                                 //获取PID VID
  65.                                                 int VID = 0, PID = 0;
  66.                                                 szTemp.MakeUpper();
  67.                                                 sscanf(szTemp.Mid(13, 4), _T("%X"), &PID);
  68.                                                 sscanf(szTemp.Mid(4, 4), _T("%X"), &VID);
  69.                                                 DevInfo stDevinfo;
  70.                                                 stDevinfo.nPID = PID;
  71.                                                 stDevinfo.nVID = VID;
  72.                                                 //设备ID号,从0开始
  73.                                                 vecDevInfo.push_back(stDevinfo);
  74.                                                 nRet = 0;
  75.                                         }
  76.                                         pProBag->Release();
  77.                                 }
  78.                                 pMoniker->Release();
  79.                         }
  80.                         pEnumMon->Release();
  81.                 }
  82.         }
  83.         CoUninitialize();
  84.         return nRet;
  85. }

  86. int _tmain(int argc, _TCHAR* argv[])
  87. {
  88.         EnumAllDevices();
  89.         for (int i = 0; i < (int)vecDevInfo.size(); i++)
  90.         {
  91.                 std::cout << "VID: " << vecDevInfo[i].nVID << "    PID: " << vecDevInfo[i].nPID << std::endl;
  92.         }
  93.         system("pause");

  94.         return 0;
  95. }

复制代码


vid.png (65.81 KB, 下载次数: 60)

vid.png
回复

使用道具 举报

29#
发表于 2022-9-11 23:25:07 | 显示全部楼层
chinaren12 发表于 2022-9-11 21:18
我这边是把打印机名字改为了p1007,刚开始第一次测试也没打出来,后面我排查了一下问题,是我两边的打印 ...

应该和ip地址没关系,倒是有可能是网络不稳定,又找到一些usb操作代码
使用API操作USB太麻烦了,[七猫]告诉我可以用LibUSB-Win32(http://sourceforge.net/apps/trac/libusb-win32/wiki)
a. 调用usb_init函数,进行初始化
b. 调用usb_find_busses、usb_find_devices和usb_get_busses这三个函数获得已找到的USB总线序列;然后通过链表遍历所有的USB设备,根据已知的要打开USB设备的ID(VID/PID),找到相应的USB设备;最后调用usb_open函数打开该USB设备(在这里假设总线上没有相同VID和PID的USB设备。如果总线上存在着相同VID和PID的设备,还需要进行其他条件判断,比如设备名称,以保证是打开的是期望的USB设备)。
c. 使用usb_control_msg函数与USB设备进行通信,向USB设备读取数据或写入数据。
d. 关闭USB设备。


回复

使用道具 举报

30#
发表于 2022-9-11 23:49:10 | 显示全部楼层
搜索一下发现还有一堆操作usb的lib,
openwrt路由器或者Linux下估计就是通过这些直接发给usb的,
理论上win也可以用,
论坛存一份介绍
关于libusb,libusbx,libusbK,libusb-win32,WinUSB的关系
刚开始接触USB驱动编程,一般是利用现成的库来做,但是网上一搜索,发现一大堆各种各样的lib把人搞的很头疼,这边总结一下。


== libusb ==
说明:libusb是一个跨平台的usb驱动框架。libusb原始项目在2010年后基本没有更新,曾有libusbx项目2012年从libusb分出来,2014年1月26日又合并回libusb了。当时的libusbx-1.0.18和libusb-1.0.18其实完全一样,相当于libusbx替换了libusb的代码!后续的版本其实都是基于libusbx的代码了!

包含两个主要分支1.x和0.1.x。
1.x和0.1.x并不兼容,可以同时存在,如果要在1.x基础上兼容0.1.x需要libusb-compat转换层。所以0.1.x和libusb-compat不能同时装上!

内核:目前1.x分支的驱动只有用户态,linux下支持usbfs,windows下支持WinUSB.sys。
也可以支持libusbK和libusb-win32(通过libusbK支持)。

工具:通过Zadig支持生成基于libusb0、libusbK、WinUSB的inf文件。
https://github.com/pbatard/libwdi/wiki/Zadig

== libusb-win32 ==
说明:libusb-win32是从libusb-0.1.x分支衍生的,
主要是针对Windows做优化,所以接口风格和libusb-0.1.x一致。

内核:WDM框架的libusb0.sys驱动。

工具:自带inf-wizard.exe生成基于libusb0.sys的inf文件。

注意:目前建议是新的项目尽可能使用libusb,而不是这个libusb-win32了。我在这个上面花了很多时间,一直报错,坑爹了,要注意libusb-win32已经废弃,目前使用的是libusb+Zadig的组合。

== libusbK ==
说明:libusbK主要是想做一个WinUSB接口风格的开源usb库,
支持基于KMDF的libusbK.sys和系统自带的WinUSB.sys。参考libusb-win32做的开发,部分工具是从libusb-win32整合而来的。因为源代码里也包含了libusb0.dll的加载功能和转换层,所以也可以支持WDM框架的libusb0.sys(libusb-win32)。

内核:基于KMDF框架的libusbK.sys、WDM的libusb0.sys、系统的WinUSB.sys

工具:自带libusbK-inf-wizard.exe(基于libusb-win32的工具改的)
生成基于libusb0、libusbK、WinUSB的inf文件。

== 备忘 ==
libusb (官方版本,2014.06.14)
新网站:http://libusb.info/
新代码:http://sourceforge.net/projects/libusb/ (新的1.0.19-2014.06.14)
新开发:http://github.com/libusb/ (貌似开发进度都在这个上面显示了)
旧网站:http://www.libusb.org/ (基于Trac的,已经废弃了)
旧网站:http://libusbx.org/
旧代码:http://sourceforge.net/projects/libusbx/ (到1.0.18-2014.01.26为止)
目前Windows下只是用户态的驱动
支持libusbK、WinUSB、libusb-win32的内核驱动访问。
如果要使用libusb-win32的话,需要安装libusbK!

libusbK(支持windows,2014.04.27)
新网站:http://sourceforge.net/projects/libusbk/
旧网站:http://code.google.com/p/usb-travis/
包含内核态和用户态驱动

libusb-win32(libusb-0.1版本的windows移植,2012.01.17)
网站:http://www.libusb.org/wiki/libusb-win32
网站:http://sourceforge.net/projects/libusb-win32/
包含内核态和用户态驱动

简单说,就是不要去管libusb-win32和libusbK项目,目前不管是windows还是Linux都是使用libusb项目,主页是libusb.info。

在Windows上使用libusb时是调用微软的WinUSB接口,在Linux上是usbfs。用Zadig工具统一安装驱动,不用理什么inf-wizard.exe。

参考 http://blog.gpjtag.com/?p=733


点评

我刚刚又测试了一遍,P1007确实可以打印了。但是,有一个小小的问题。 就是如果实际连接打印机的电脑不打印,共享的电脑打印的话,第一次打印不会成功。按了打印之后,打印会有一个短暂的唤醒动作,然后就没反应  详情 回复 发表于 2022-9-12 09:36
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-6-14 07:18

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表