如何将打印机驱动程序转换为独立的控制台应用程序,该应用程序可以生成包含要发送到打印机的字节的打印机文件?

我有一种情况,生成一个特定的数据文件的唯一方法是手动打印到文件:在Windows下,并将其保存在文件中进一步处理。

我真的希望有一个embedded这个二进制打印机驱动程序的小型独立程序,这样我就可以从一个batch file运行它,让它为我生成二进制文件,因为我们可以完全自动化“在Visio中保存文件, “打印”并将其上传到最终目的地并触发远程testing“。

这可能与一个合适的Windows SDK? 我是一个Java程序员,所以我不知道Visual Studio和MSDN的可能性 – 但! – 但我会欣赏指针。


编辑:我有该打印机驱动程序的安装文件,32位和64位。 旧版本可能包括一个16位驱动程序。


编辑:“打印到文件:”function正是文档所build议的。 我使用LPR协议玩了一下,看看它能做什么。 我仍然更喜欢“调用小二进制”的方法。

你制定的一般问题很难解决。 大多数打印机驱动程序包含一些众所周知的组件,如“打印监视器”,“打印处理器”等,这些组件在Windows驱动程序工具包http://msdn.microsoft.com/zh-cn/library/ff560885%28v=VS.85% 29.aspx 。 几年前我写了一个打印监视器。 它在一个客户工作了很多年。 所以我确切地知道我在写些什么。 打印监视器不过是一个具有良好文档功能的DLL。 大多数其他打印机组件也是如此。 这些DLL将被加载并从后台打印程序调用。 如果你有一个现代化的打印机驱动程序,它没有在内核模式下运行的组件。 所以可以加载大部分由每个打印机驱动程序组成的DLL,并调用相应的函数

您使用一个音乐会打印机驱动程序是有趣的。 所以第一个应该做的就是研究这个驱动程序是如何实现的。 如果你发现哪个组件做了你需要的工作,你可能会在你的进程中加载​​这个DLL并产生你需要的输出。 您可能会发布一个URL,我可以下载这个驱动程序?

更新 :我多了一点关于你的要求。 在我看来,您可以按照打印机驱动程序开发人员的建议方式进行操作。 如果驱动程序可以打印到本地端口文件,那么它可以打印在任何打印机端口。 因此,您可以从C:\ WinDDK \ 7600.16385.1 \ src \ print \ monitors \ localmon提供Port Monitor server驱动程序的src(另请参阅http://msdn.microsoft.com/zh-cn/library/ff556478%28v = VS.85%29.aspx , http://msdn.microsoft.com/en-us/library/ff549405%28v=VS.85%29.aspx和http://msdn.microsoft.com/en-us /library/ff563806%28v=VS.85%29.aspx )。 (我是一个Windows 32/64 DLL,而不是一个真正的驱动程序),并做了小的修改。 您可以将结果分派给您的应用程序,而不是将结果保存到文件中。 这将是100%的工作,没有任何花招。 如果你将有一些问题来了解localmon,我可以给你一些提示。 这真的不复杂。 您所要做的主要更改是从localmon.c修改LcmStartDocPort LcmWritePort LcmReadPort LcmEndDocPort函数。 一些简单的东西是区分端口DLL与典型的DLL,而不是导出所有DLL的函数,它只导出一个InitializePrintMonitor2指针到所有其他函数。

更新2 :使用“本地端口”监视器的另一个提示。 如果进入打印机配置,然后选择“添加端口…”,选择“本地端口”,然后单击“新端口…”,您可以键入任何文件名称,如“C:\ temp \ my.bin”。 然后,所有通过打印机打印的内容都将被打印在这个文件中,而不需要用户迭代。 名称可以是任何 win32文件名(UNC名称或命名管道也是允许的)。 通过这种方式,您可以在不使用DDK编程的情况下实现一些场景。

更新3 :我从不同的侧面看打印机驱动程序,并再次在DDK API中查看。 现在我想推荐你选择最简单的方式,并从驱动程序制造商全面支持的方式。 我建议如下:

您可以使用您需要的驱动程序安装打印机,并选择具有固定文件名的本地端口作为输出端口(请参阅更新2)。 我在这里命名目标文件名为C:\ TEMP \ Output.afp 。 所以你收到像推荐你司机制造商一样的情况。 固定的文件名与FILE: port 完全一样。 因此,如果您打印到您在C:\ TEMP目录中的Output.afp文件中收到的打印机。 为了确保编写的结束,您可以使用ReadDirectoryChangesWFindNextChangeNotification / FindFirstChangeNotification函数, dwNotifyFilter等于FILE_NOTIFY_CHANGE_LAST_WRITE 。 然后在文件的最后写入时间之后收到通知。 这意味着写入结束之后和FileClose之后以及缓存充分刷新之后。 所以文件Output.afp没有被锁定,你可以真正安全地读取结果。

对于简单文档的打印,您可以使用WritePrinter函数(请参阅http://msdn.microsoft.com/en-us/library/dd162959%28VS.85%29.aspx和文档http://msdn.microsoft中的注释。 com / en-us / library / dd145226%28VS.85%29.aspx )。 使用位图,颜色和不同字体编写复杂文件时,必须使用典型的GDI API,例如Windows中的一个(请参阅http://msdn.microsoft.com/zh-cn/library/dd162865%28v=VS.85%29 .aspx )。

这个解决方案看起来不像写一个打印机驱动程序组件或打印机驱动程序假脱机程序环境的仿真,但它将工作,将安全工作,并将得到驱动程序制造商的全力支持。

(我做了这样的事情已经有10年了,但是我不认为整体概念已经改变了很多:)

你想要做的是实现一个自定义的打印处理器。 打印处理器是将打印机驱动程序生成并输出到输出设备的输出代码。 打印处理器被实现为常规的用户模式DLL。 您应该能够在Windows DDK中找到所需的所有东西,包括样本。

前一段时间,我们做了一个商业应用程序,从任何Windows应用程序捕获打印流,并将结果转换为XML和TIFF图像
我们确实使用DDK制作了一个原型,但是最终购买了一个用于打印捕获的SDK
SDK来自BlackIce 。 虽然它不是免费的SDK,但是运行时的版本是免费的。

实现是用Visual C(非托管)和VB6完成的。 打印机驱动程序必须安装在驱动打印过程的服务器/ PC上。
我记得那个棘手的部分是在运行时控制打印机设置(保持压缩的tiffs,文件的输出目录,纸张大小:在DEVMODE打印控制结构中定义的A4或Letter以及其他设置)。

更新:( 你对@ Oleg的评论关于MO:DCA P触发了我的内存,虽然它不是关于打印机驱动程序…)
对于我们的商业产品,我们还必须定制将MO:DCA(AFP)文档转换为tiff和XML。
此SDK必须能够提取图像和ASCII文本,以便以后进行转换
然后从一个文件夹中的AFP文档批量转换成XML和tiff。
我们选择将AFP文件打印后(不打印时)进行转换。
SDK是SnowBound RasterMaster ,可用于不同的风格(我们使用Windows API与ActiveX,现在我看到它可用于Java )
因此,如果您的要求是将AFP文档转换为其他文件(提取图像并提取ASCII文本),则可以从SnowBound试用软件。 请确保您还获得可选功能 ,以便能够从MO DCA文档中提取ASCII文本。
这个软件SDK比较昂贵,但是它做了这个工作。
他们在这里提供试用版。

目前我在你的解释中有一个缺失的链接,所以让我重新说明我所理解的:

  • 您的Windows系统上有一个特殊的打印机驱动程序,它被配置为打印到一个文件中。
  • 你喜欢有一个简单的批处理程序,可以给这个打印机驱动程序输出一个二进制文件的东西。
  • 你有一个工具链,这个文件可以进一步处理。

现在我缺少的部分是,你想给你的小批量脚本,以便它产生你的二进制文件? 你有一个Visio文件,应该通过这个驱动程序自动打印?

如果是的话,你应该看看这个小批处理脚本 。 它可以将任何带有已注册文件扩展名的文件以默认设置发送到默认打印机。 通过使用这些设置,您可以在批处理文件中更改Windows系统中的打印机设置,以使您的特殊驱动程序成为默认驱动程序,并将输出结果放入文件中。

所以,如果我正确地理解你,我没有完整的解决方案,但我认为一个很好的起点来完成你的任务。

更新

好吧,看完你的评论后,我完全明白你想达到什么目的。 为了得到这个工作,你必须遵循Per Larsens的建议,用windows ddk编写你自己的驱动程序(或者更精确地说是Windows驱动程序工具包[WDK] )并封装已经存在的驱动程序。

所以简而言之:您的驱动程序注册为新的打印机驱动程序。 当它被调用时,它从应用程序获取所有的原始字节。 将其传递到可以生成数据文件的驱动程序中。 从驱动程序得到输出,并用它来做任何你喜欢的事情。

一些样本开始也可以在MSDN中作为总览或更精确地在这里找到 。

但是事先说好:这不是一件容易或者简单的事情,而且这个努力是相当高的。 也许试图通过已经提供的批次或简单的应用程序(使用AutoIt编写)来操作特殊驱动程序的驱动程序设置也可以通过与驱动程序的设置进行交互(自动)来解决您的问题。

我可以生活在“当用户打印任何文件到这台特定的Windows打印机,然后自动捕获将被发送到打印机的字节”。

在这种情况下,你需要像RedMon这样的东西,它将把打印机中的字节重定向到另一个程序的输入中。

只是重申,最简单的捕获方法可能是使用一个新的本地端口配置为文件名。 您可以像前面讨论的那样监视输出文件来捕获输出。

否则,您要编写自己的端口监视器 – 不是打印机驱动程序或打印处理器。 所有的端口监视器都会从打印机驱动程序接收已经渲染的数据,并将其发送到输出设备。 因此,编写自己的端口监视器将允许您进入并将与现有打印机驱动程序关联的输出端口更改为您自己的输出端口,并且您的端口监视器可以简单地将数据写入文件,可能只有一个文件名一个专门的目录。

打印机驱动程序对于您想要执行的操作来说太复杂了,而打印处理器也可能捕获输出数据,所以您可能会纠结于一些您不想要弄清楚的文件系统问题。

Windows Driver Kit中的LocalMon示例是编写端口监视器的起点。 但是,它管理着所有的系统本地端口,比你需要的要复杂得多。 事实上,其中大部分可能会让你感到困惑。 我建议你从LocalMon开始,并将其与Redmon源进行比较,因为它管理的是专用端口,所以这更简单得多。 请注意,Redmon源很早以前就已经从localmon中获得了,并且似乎有一些bug,所以使用Redmon作为参考,并将LocalMon代码删除,直到将输出写入文件。

您不要将驱动程序嵌入到可执行文件中 – 驱动程序需要操作系统与硬件进行通信。

您可以通过操作系统进行打印。

您的“批”需要选择正确的打印机,并打印…