1.4、Windows本地打印任务处理流程

1.4.1、本地打印机的架构

对Windows的本地打印任务处理的流程的说明,我想从打印机接入计算机或者操作系统说起。在这里我们仅仅针对本地计算机,因此,打印机和计算机之间,通过本地连接的话,他们之间就必须要有某一个介质和通信的协议来进行相互之间的数据传输。其中,介质归纳来说,合计有三种:USB、LPT(并口)、COM(串口)【当然了现在还有无线、蓝牙这样的介质打印机】。而在这里我所指的本地打印机,就是通过(计算机本地的LPT(并口)、COM(串口)或者USB口的连接)的打印机。本地打印机和计算机之间的通信协议就是LPT(并口)、COM(串口)或USB口决定的:是一种协议总线,即主机与设备之间的通信需要遵循一系列约定。比如USB协议、LPT(并口)以及COM(串口)协议,他们之间的控制语言就是ESC或ESC/P2。当然,这也并非放之四海而皆准,比如有一些打印机厂商,他在设计这个打印机的处理模块的时候,不同的打印机支持的协议都不完全相同。

USB生活中比较常见,大家对它都比较熟悉,这里我想简要提几句LPT(并口)和COM(串口)。LPT一般来说是提供给打印机专用的端口和协议,LPT并口是一种增强了的双向并行传输接口,在USB接口出现以前是扫描仪,打印机最常用的接口。一般有25针/孔和36PIN两种型号。并行接口是指数据的个位同时进行传送,其特点是传输速度快,但当传输距离较远、位数又多时,就导致通信线路复杂且成本提高。至于COM呢?COM接口也就是串口接口,一般是9针或者是9孔的接口,也称串行通信接口,是采用串行通信方式的扩展接口。串行通讯的特点是:数据位的传送,按位顺序进行,最少只需一根传输线即可完成;成本低但传送速度慢。串行通讯的距离可以从几米到几千米。老式的那种针式打印机或者现在部分的激光打印机还在使用COM口,部分激光打印机使用USB接口。COM最开始的作用仅仅是连接老式的鼠标,还有就是调试设备时使用,这个最广泛的例子就是交换机的调试端口Com口。现在来说:打印机采用USB接口的最多,因为USB接口的传输速度比LPT和COM快很多!

因此,本地打印系统中通常包含一台计算机(请求打印设备,当然不仅仅只有计算机)和一台打印机,此二者通过通信线缆(USB、LPT、COM)连接起来,计算机通过通信线缆向打印机发送打印数据,打印机完成打印数据的打印。目前,打印系统一般通过两种方式完成打印数据的打印,一种是在计算机上安装专用应用程序,比如针对某一行业或某一客户需求开发的应用程序,由专用应用程序直接向打印机发送可以被打印机识别的打印命令和打印数据,打印机接收到打印命令和打印数据后执行打印数据的打印;另一种是在打印请求设备上安装通用应用程序(比如Office办公软件),同时,在计算机上安装由打印机制造商提供的打印机驱动程序,应用程序生成图形数据后调用打印机驱动程序,使打印机驱动程序生成包含可被打印机识别的打印命令和打印数据的作业数据,计算机将作业数据发送到打印机,打印机接收到作业数据后执行打印数据打印。

下图显示了本地打印任务的流程图:

如图所示,应用程序通过GDI接口创建打印任务后,不管是否需要输出为EMF,本地的PrintProvider任务创建API都会创建一个Spool文件。然后,当任务被调度的时候,通过读取这个Spool文件,如果是EMF格式的话,就让EMF打印处理器配合打印机的渲染驱动,将打印任务发送回去给GDI转换成RAW格式,最后和没有使用EMF格式的任务一样,将数据流传递到端口监视器中执行最终打印。

下面我们来细细解析这一过程!

1.4.2、本地打印处理流程解析

流程1:应用程序枚举打印机

首先第一步,用户在编辑Word完成之后,想将这个Word打印出来,于是用户就点击了Word的功能按钮“打印”!当用户点击了这个按钮之后,Word应用程序通过打印API函数或打印相关的通用对话框枚举Windows打印池客户DLL,找到当前打印机的信息。

Windows打印池客户DLL首先接受到这个“打印”的请求之后,第一步就是初始化打印机下拉列表选项

Windows打印池客户DLL如何枚举打印机的信息呢?

对于Windows操作系统,操作系统的打印管理系统提供语言监视器(Language Monitor)组件和端口监视器(Port Monitor)组件,由语言监视器组件和端口监视器组件完成作业数据的发送和打印机的状态的获取。这两个组件我在打印假脱机程序(Print Spooler)已经提到过。语言监视器(Language Monitor)组件和端口监视器(Port Monitor)组件是由打印假脱机程序(Print Spooler)控制或调用的。因此,整个枚举(通过EnumeratePrinters函数)的过程是这样的:

1、枚举本地打印机。

Windows打印池客户DLL通过RPC将枚举打印机的请求提交给打印假脱机程序(Print Spooler),打印假脱机程序(Print Spooler)接受到该枚举打印机的请求之后,该程序首先会去枚举自己的注册表或者数据库中的打印机信息和打印作业状态。默认情况下,当我们在将打印机接入计算机时,都会在计算机上安装相应的打印机驱动程序并识别打印机。这个过程就是把打印机的信息预先填充到了打印系统的数据库中。识别打印机的这一过程和计算机识别一个U盘是一样的流程,在这里我就不做说明。

Windows打印池API提供了专门的枚举打印机的函数,打印假脱机程序(PrintSpooler)可以用它枚举打印机及查询打印机信息。这里面枚举的过程很复杂,有很多选项,返回很多不同类型的结构,可用于枚举本地打印机、打印提供者、域名及计算机域名内的所有打印机和打印服务器,然后将这些枚举出来的信息填充到打印假脱机程序(Print Spooler)的打印机信息结构数组。这个结构数组包含了服务器名、打印机名、共享名、驱动程序名、DEVMODE、单个文件、打印处理器、打印池数据类型、安全描述符等。这样的一个结构数组就提供了打印机的完整信息。

2、枚举打印机状态信息。

打印假脱机程序(Print Spooler)在获取到打印机信息结构数组的完整结构之后,根据结构数组里面的打印机列表,再分别枚举这些打印机的连接情况。怎么去枚举物理打印机的连接信息或者说状态信息呢?这也是一个比较难说明的过程。首先,我需要告诉大家的是,确定一台物理打印机的状态的前提条件是:必须尝试通过打印后台处理程序将打印作业发送到物理打印机才能够最终确定物理打印机的状态。但是在这个时候,我们明显的是没有打印任务给到打印机的(假设就一台打印机而且计算机是单用户操作系统,Word打印任务还没发布出来呢)。

Windows为这种情况下提供了两种方法来获取物理打印机的状态信息:

第一种方法,读取用于特定的打印作业的JOB_INFO结构的状态信息从而判断物理打印机的状态。JOB_INFO结构包含位于操作系统上的逻辑端口的状态信息和物理端口的状态信息。物理端口在计算机中又将其分为第一设备通道和第二设备通道,逻辑端口则具有第一逻辑通道和第二逻辑通道,计算机上的打印系统和端口监视器用于通过第一设备通道和第一逻辑通道向打印机发送打印数据,端口监视器用第二设备通道和第二逻辑通道监控打印机的状态,因此,通过这两个成员端口监视器就可以报告打印作业的状态信息。这两个成员在默认情况下包含预设的值,这些值是由Win32 SDK和WinSpool.h头文件记录。JOB_INFO结构有两个API函数︰GetJob和EnumJobs。这个状态信息里面记录的其实就是GetJob和EnumJobs的信息,也就是打印机的打印作业的记录和打印作业的状态信息,这些打印作业的状态信息会存入到JOB_INFO结构中。通过读取JOB_INFO结构的状态信息,如果不存在打印作业且打印作业队列为空,那么我们就认为打印机已就绪并处于闲置状态。

第二种方法,通过检查PRINTER_INFO结构的状态。PRINTER_INFO的结构是由GetPrinter函数返回的。GetPrinter函数的作作用是取得与指定打印机有关的信息。相应地,这个函数是在进行打印作业的时候从打印机获取到的打印机信息。当没有打印作业执行的时候,该函数返回的是默认的设定好的值。通过读取这个PRINTER_INFO结构的状态也可以大致得到物理打印机的链接状态信息。但是,这两组结构的状态可能与真实的物理打印机的状态并不严格的契合。如果这个时候,物理打印机处于错误状态如离线。操作系统也会认为打印机可以接受打印作业。这种情况下,端口监视器会讲端口断线的消息给到后台的打印系统,并且这个错误信息只会到用户的操作系统中,并在操作系统中显示错误状态而不会通知用户。因此,用户在这种情况下选择打印,枚举出来打印机之后,在发生打印数据的过程中就会出现错误。

3、在列表框中列出打印机。

完成上述两个步骤之后,打印假脱机系统就会将枚举出来的打印机的信息以及状态发送给到Windows打印池客户DLL。Windows打印池客户DLL第一步将这些打印机的名字加到列表框中,用户可用这个列表框来选择打印机。然后通过函数判断是否有选中值。

Windows API函数:【http://baike.baidu.com/link?url=JDDbqL_kzikpGQCJX8JqdT-gpDBLRbvu_94Ohv40d7eLvzvbyMqeAsfuE4KnUdTMl7pY7DW6Q_KAPWLoxy4wwa】

计算机调用打印机打印流程图,Windows打印体系结构之本地打印任务处理流程①...相关推荐

  1. 在计算机上打印机,如何在Windows计算机上安装本地打印机 | MOS86

    打印机在世界各地的家庭和办公室中都很常见.要在打印机上打印任何内容,必须将其连接到计算机并进行安装.最常见的方法是使用USB线.如果您不知道如何操作,本指南适合您:我们将演示如何使用USB连接在任何W ...

  2. java打印word_Java jacob调用打印机打印word文档

    前面说了Java如何生成复杂的Word文档,今年记录下Java如何调用打印机打印word文档. 起初用的是自带的PrintJob,但是系统提供的打印机制并不成熟完整.网上的代码也是千篇一律,在我的打印 ...

  3. 共享计算机添加打印机后无法打印机驱动,打印机无法打印原因?打印机设置共享的方法...

    我们平常也经常打印资料,那么打印机是什么呢?小编给大家科普一下,打印机是计算机的输出设备之一,用于将计算机处理结果打印在相关介质上.衡量打印机好坏的指标有三项:打印分辨率,打印速度和噪声.将计算机的运 ...

  4. C#实现调用打印机(打印字符串、打印绘图、打印图片),还差打印水晶报表

    C#实现调用打印机(打印字符串.打印绘图.打印图片),还差打印水晶报表 目的:调用打印机的使用 缺陷:打印的对象不全(还差打印水晶报表),不能实现在插件绘图板中画什么打印什么 改进:同缺陷,希望朋友们 ...

  5. C++ 调用打印机 打印一段文字

    系统:win7 环境:VS2010 语言:c++ 函数:调用打印机打印一段文字. void CpainttestDlg::OnClickedButton1() {// TODO: 在此添加控件通知处理 ...

  6. 手机文档怎样通过计算机打印,惠普M1218怎么使用手机打印文件?电脑与电脑之间怎么共享打印机打印?...

    您好 打印机支持wifi功能,但不支持wifi dricet,所有无法实现手机无线直接连接打印机进行打印,如果手机和打印机在同一wifi环境下,手机方式app尝试搜索打印机,但不确认一定可以实现打印. ...

  7. Unity调用打印机打印文本或者图片

    Unity调用打印机打印文本或者图片 通过windows命令行使用记事本打印文本 private void PrintTxt(){//picPath=Application.streamingAsse ...

  8. windows无法打开添加打印机 本地打印后台

    2019独角兽企业重金招聘Python工程师标准>>>        一般很多人在打印的时候或许,都会碰到过这样的情况,点添加打印机后就提示:windows无法打开"添加打 ...

  9. Java调用打印机打印pdf

    要在Java中调用打印机打印PDF,可以使用Java打印API和第三方库,如Apache PDFBox或iText PDF. 以下是使用Java打印API打印PDF的基本步骤: 安装打印机:确保您已经 ...

  10. python调用打印机打印图片_在python中通过图像发送到打印机上的文本

    在 windows系统中使用 python,wx python和sqlite.我正在尝试打印一些证书/文凭/卡片,背景中有图像,上面有人/文字的名称. 我知道使用来自Pywin32的win32prin ...

最新文章

  1. python构建cnn图片匹配_tensorflow搭建cnn人脸识别训练+识别代码(python)
  2. 国贫县山西永和:“一揽子”保险“保”脱贫
  3. MongoDB —— 概念简述
  4. 几种字符串加密解密的方法
  5. 分公司部署加速设备实现广域网加速
  6. goldengate for mysql_GoldenGate for mysql to mysql:单向同步
  7. python docx 表格打印不显示_python-docx 设置 word 文档中表格格式
  8. MEncoder的基础用法—6.6. 改变电影大小
  9. linux tomcat8+jdk1.8u201百度云盘下载
  10. 我为App做测试---搜狐新闻(1)
  11. 面试常见简单编程题目
  12. 常见的导数公式和积分公式
  13. 20155310《网络对抗》免杀原理与实践
  14. Java 网络编程:(七)UDP网络编程
  15. 通过hutool工具包实现将数据库中的全量数据导出,一张表一个sheet页,包含目录页,目录页和sheet页之间可以互相跳转
  16. 服务器xp系统网页打不开网页,ie浏览器打不开网页,xp系统ie打不开网页-
  17. FLASH,宣传画册,翻书效果
  18. Image Thresholding图像阙值化和Adaptive Thresholding
  19. python把日期数据转换成数字_python3时间datetime如何转换成数字?
  20. 关于版权声明的格式 (Copyright)

热门文章

  1. 科研学术论文搜索利器:Publish or Perish
  2. python素数的判断方法_判断是否是素数(质数)的几种简单方法
  3. freekan电影网站制作教程
  4. sketch如何做设计稿交互_sketch 交互原型制作方法
  5. 漫威电影宇宙观影指南,口碑票房最佳都是谁
  6. ASO学习笔记整理——关键字优化步骤
  7. echarts 柱状图颜色及渐变色设置
  8. 录像机人机界面蓝屏怎么处理
  9. 吐槽国内各大公司的漏洞报告平台
  10. C# 基础 (3) 垃圾回收机制(Garbage Collector)