调试打印机驱动程序组件

如果要开发呈现插件或用户界面插件的打印机驱动程序,可以在这些组件中启用调试消息。 如全局调试变量部分所述,可以使用全局调试变量来控制调试器窗口中显示的消息中的详细信息级别。

可以使用调试消息宏部分中讨论的宏,在各种条件下将消息发送到调试器窗口。 此外,可以使用本部分中的信息启用 Microsoft 通用打印机驱动程序 (Unidrv) 或 PostScript 打印机驱动程序 (Pscript) 呈现器中的调试消息,前提是你已检查这些 DLL 的内部版本。

注意

Windows 10 版本 1803 之前的旧版 Windows 上提供已检查的版本。 使用驱动程序验证器和 GFlags 等工具在更高版本的 Windows 中检查驱动程序代码。

接下来的两个部分将介绍调试用户模式驱动程序的步骤和一些常规调试提示。

准备User-Mode调试

若要开始调试打印机驱动程序及其组件,请执行以下操作:

  1. 安装最新的调试工具。 请参阅 下载适用于 Windows 的调试工具

  2. Windows 符号包安装正确的符号

注意

使用最新版本的调试器非常重要。

建议仅安装你有兴趣调试的组件的已检查版本。 通常,你会将以下零售二进制文件替换为相应的检查版本:

  • Unidrv.dll

  • Unidrvui.dll

  • Unires.dll

还应安装已检查的 Oemuni 示例版本或要调试的打印机驱动程序。 与安装整个检查的生成系统不同,使用此方法的优点是不会降低整个系统的速度。

启动User-Mode调试会话

若要开始用户模式调试,请在 Windbg 调试器的“ 文件 ”菜单上选择“ 附加到进程”。 将调试器附加到的过程取决于尝试调试的方案。 对于打印机驱动程序,必须将调试器附加到打印应用程序或后台处理程序进程 (Spoolsv.exe) 。 请记住,打印应用程序加载配置/用户界面模块,而后台处理程序进程加载呈现模块。 但是,“FILE:”打印存在差异,其中不进行后台打印,因此,打印应用程序也会加载呈现模块。 因此,必须确保附加到正确的进程。

注意

用户模式调试不需要两个单独的计算机。

以下过程将帮助你准备好调试 Oemuni 示例。

  1. 在“FILE:”端口上安装 Oemuni 示例。

  2. 通过单击“ 开始 ”菜单、选择“ 所有程序”、“ 附件”和“ 写字板”来启动写字板应用程序。

  3. 在“WinDbg 文件 ”菜单上,选择“ 附加到进程”。 在可用进程列表中,选择 “WordPad.exe”。

  4. 从写字板启动打印作业。 现在可以调试 Oemuni 示例了。

可以通过打开 giDebugLevel 变量来启用详细调试。 其默认值为 3,表示 WARNING。 如果设置为 1,则表示 VERBOSE。 若要使用 Unidrv.dll 设置后一个值,请在调试器中键入以下命令:

> ed unidrv!giDebugLevel 1

运行 Oemuni 示例时,相同的调试变量也适用,因此若要启用详细调试,请键入以下命令:

> ed oemuni!giDebugLevel 1

还可以将自己的调试语句添加到 Oemuni 示例。

有关设置调试值的详细信息,请参阅 WinDbg 文档,其中介绍了可用的命令并概述了设置用户模式调试所需的步骤。 若要访问文档,请在“WinDbg 帮助 ”菜单上选择“ 内容”。

全局调试变量

giDebugLevel 全局变量由 Oemui 和 Oemuni 示例在其 Debug.h 和 Debug.cpp 文件中声明。 giDebugLevel 的值可以通过以下方式修改:

  • 在调试器中更改其值
  • 在插件中重新定义其值

可以将 giDebugLevel 设置为以下任何值:

#define DBG_VERBOSE 1
#define DBG_TERSE   2
#define DBG_WARNING 3
#define DBG_ERROR   4
#define DBG_RIP     5

调试消息宏

以下宏用于调试。 仅当控制发出调试消息的 giDebugLevel 全局变量设置为特定值时,其中一些才会采取措施。 宏在免费版本中扩展为空白。 下面是它们的功能及其参数的简要说明。

ASSERT (cond)

  • 验证 cond 中的布尔表达式是否为 TRUE。 否则,宏将强制使用断点。

ASSERTMSG (cond, (msg) )

  • 验证 cond 中的布尔表达式是否为 TRUE。 如果不是,宏会在 msg 中显示消息,并强制设置断点。

ERR ( (msg) )

  • 如果当前调试级别为 <= DBG_ERROR,则显示 msg 中的消息。 消息格式为:

    ERR filename (linenumber): msg
    

RIP ( (msg) )

  • msg 中显示消息并强制设置断点。

TERSE ( (msg) )

  • 如果当前调试级别为 <= DBG_TERSE,则显示 msg 中的消息。

VERBOSE ( (msg) )

  • 如果当前调试级别为 <= DBG_VERBOSE,则显示 msg 中的消息。

WARNING ( (msg) )

  • 如果当前调试级别为 <= DBG_WARNING,则显示 msg 中的消息。 消息格式为:

    WRN filename (linenumber): msg
    

请注意,所有具有 msg 参数的宏都需要围绕此参数的额外括号对。 下面是说明此要求的两个示例:

ASSERTMSG(x > 0, ("x is less than 0\n"));
WARNING( ("App passed NULL pointer, ignoring...\n") );

包含 msg 参数的宏由 Oemui 和 Oemuni 示例在其 Debug.h 标头中定义。