JavaScript 约束

重要

建议使用 Microsoft 的 IPP 收件箱类驱动程序以及打印支持应用 (PSA) 来自定义 Windows 10 和 11 中的打印体验,以便进行打印机设备开发。

有关详细信息,请参阅打印支持应用设计指南

v4 打印机驱动程序模型支持从 v3 IPrintOemPrintTicketProvider 接口派生的扩展约束和 PrintTicket 处理的新模型。

但是,v4 打印机驱动程序不使用已编译的配置插件,而是使用 JavaScript 实现称为 JavaScript 约束的 API,并且打印机驱动程序可以根据需要实现其中一个或多个 API。 有关详细信息,请参阅本主题末尾的 JavaScript 约束 API 部分中的函数。

JavaScript 约束可用于增强 PrintCapabilities、验证 PrintTickets 并处理 PrintTicket 到 DEVMODE转换,反之亦然。 但是,JavaScript 约束有一些限制。 下面是主要限制的列表:

  • 使用 CompletePrintCapabilities 添加的功能和选项以及 validatePrintTicket 中指定的约束不会显示在桌面打印机首选项窗口中。

  • 使用 CompletePrintCapabilities 添加的功能和选项不会保存到公共 DEVMODE 中。

  • JavaScript 约束无法访问资源 dll 中的语言资源,以本地化添加的功能和选项或参数。

因此,我们建议仅在适当情况下使用 JavaScript 约束。 应尽可能在 GPD 或 PPD 文件中指定功能和选项,并且只应在 JavaScript 中表示复杂的约束。

调试 JavaScript 文件

通过在基于 Windows 的脚本主机中打开 JavaScript 文件来支持 JavaScript 文件的基本语法验证。 为此,请右键单击 JavaScript 文件并选择“打开方式,然后在列表中选择基于 Windows 的脚本主机条目。 如果未引发错误,则 JavaScript 在语法上有效。 否则,它将指出问题的行号,如以下屏幕截图所示。

javascript 语法错误对话框。

公开提供的 JavaScript 验证工具在评估 JavaScript 文件的样式方面也可能是有价值的助手。

可以通过创建以下注册表项来启用交互式调试:

键名称: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print

值名称: EnableJavaScriptDebugging

类型:DWORD

值: 1

但是,由于 经常加载和卸载PrintConfig.dll ,因此调试打印的应用不是建议的测试/调试策略。 相反,Microsoft建议制造商生成一个测试应用,该测试应用使用这些公共 API 调用 JavaScript 约束的每个相关入口点:PTGetPrintCapabilities、PTConvertDevModeToPrintTicket、PTConvertPrintTicketToDevModePTMergeAndValidatePrintTicket

仅测试应用就足以启用调试,但添加单元测试也是有益的,以确保整个驱动程序按预期处理 PrintTicket、PrintCapabilities 和约束。 有关如何在 Visual Studio 中生成单元测试的详细信息,请参阅以下主题:

Visual Studio Team Test 的单元测试演练

创建上述文本中显示的注册表项并重新启动托管进程后,可以调试 JavaScript 源文件。

请务必注意,如果源文件无法分析,则不会调用调试器,并且似乎调试环境已失败。 如果源文件无法分析,请参阅 Windows 脚本主机 ,了解有关如何继续操作的详细信息。

如果没有错误,并且源文件已成功分析,请调试源文件,如下所示:

  1. 在测试计算机上安装 Microsoft Visual Studio 2012 或更高版本

  2. 使用具有约束 JavaScript 代码的驱动程序创建打印队列

  3. 将此打印队列设置为默认值。

  4. 启动测试应用或打印并启动会导致调用 JavaScript 约束的方案。 应用必须调用 PrintTicket/PrintCapabilities API 才能闯入 JavaScript 约束;旧版应用(如记事本)不会调用这些 API,但 XPS 查看器应用会调用。 Microsoft建议在此处使用测试应用,因为可以更轻松地隔离和重现这些方案。

  5. 此时,“Visual Studio 实时调试器”将弹出,指出“应用中>发生了<未经处理的异常”

  6. 启动 Visual Studio 2012 或更高版本的新实例

  7. 选择“调试”,然后选择“附加到进程”

  8. 在“附加到进程”对话框中,确保“附加到:”设置为脚本代码

  9. 现在选择测试应用或应用打印,最后选择“附加”

  10. 单击“全部中断”

  11. 现在返回到“Visual Studio 实时调试器”对话框,然后单击“否”

  12. Visual Studio 将在当前测试调用的位置进入调试器。 现在可以正常调试代码。

JavaScript 约束 API

本部分指定用作用于 JavaScript 约束文件的 API 入口点的函数。 以下是函数:

  • validatePrintTicket

  • completePrintCapabilities

  • convertDevModeToPrintTicket

  • convertPrintTicketToDevMode

validatePrintTicket 函数

调用此 API 以验证 PrintTicket 对象是否对特定打印机有效。 这类似于 IPrintOemPrintTicketProvider::ValidatePrintTicket API 的函数

validatePrintTicket 语法

function validatePrintTicket(printTicket, scriptContext)

validatePrintTicket 参数

validatePrintTicket 返回值

返回值 说明
0 指示 printTicket 参数无效,无法更正。 等效于 E_PRINTTICKET_FORMAT
1 指示 printTicket 参数是此打印机的有效 PrintTicket。 等效于 S_PT_NO_CONFLICT
2 指示 printTicket 参数已修改,使其有效。 等效于 S_PT_CONFLICT_RESOLVED

completePrintCapabilities 函数

调用此 API 以允许修改 PrintCapabilities 对象。 这应用于条件功能(例如,照片纸上仅支持无边框)或表示无法由 GPD 或 PPD 文件(例如嵌套功能定义)生成的功能。 这类似于 IPrintOemPrintTicketProvider::CompletePrintCapabilities API 的函数

completePrintCapabilities 语法

function completePrintCapabilities(printTicket, scriptContext, printCapabilities)

completePrintCapabilities 参数

completePrintCapabilities 返回值

无。

convertDevModeToPrintTicket 函数

调用此 API 可将 DEVMODE 属性包中的值转换为 PrintTicket。 这与 IPrintOemPrintTicketProvider::ConvertDevModeToPrintTicket API 的函数类似,只是此实现将 DEVMODE私有部分封装到 IPrinterScriptablePropertyBag 对象中,并且不允许访问 DEVMODE 的公共部分。

convertDevModeToPrintTicket 语法

function convertDevModeToPrintTicket(devModeProperties, scriptContext, printTicket)

convertDevModeToPrintTicket 参数

  • devModeProperties

[in] 表示 DEVMODE 属性包的 IPrinterScriptablePropertyBag 对象。

convertDevModeToPrintTicket 返回值

无。

convertPrintTicketToDevMode 函数

调用此 API 可将值从 PrintTicket 转换为 DEVMODE 属性包。 这类似于 IPrintOemPrintTicketProvider::ConvertPrintTicketToDevMode API,只是此实现将 DEVMODE 的私有部分封装到 IPrinterScriptablePropertyBag 对象中,并允许访问 DEVMODE 的公共部分。

convertPrintTicketToDevMode 语法

function convertPrintTicketToDevMode(printTicket, scriptContext, devModeProperties)

convertPrintTicketToDevMode 参数

  • printTicket

    [in]表示 要转换的 PrintTicket 的 IPrintSchemaTicket 对象。

  • scriptContext

    [in]提供 对驱动程序属性包、队列属性包和用户属性包的访问权限的 IPrinterScriptContext 对象。

  • devModeProperties

    [in][out] 表示 DEVMODE 属性包的 IPrinterScriptablePropertyBag 对象。

convertPrintTicketToDevMode 返回值

无。

约束最佳做法

Windows 8 打印对话框和打印首选项体验仅支持打印架构关键字命名空间的子集。 因此,Microsoft不建议在 Windows 8 打印对话框支持的功能或打印首选项 UI 和不属于该 UI 的功能之间使用约束,因为用户将没有机会解决此类约束。

例如,如果名为 Photo 的 PageMediaType 选项仅限于使用 1200dpi 的 PageResolution 值,则用户将永远无法选择照片媒体类型。 在这种情况下,最好匹配用户的意图(照片媒体),并调整任何必要的设置,以使这种情况发生。 这些调整可以在 JavaScript 约束代码中进行。

如果驱动程序不使用 JavaScript 约束,则不需要提供文件。 如果驱动程序仅对入口点的子集(例如 validatePrintTicket)使用 JavaScript 约束,则应从 JavaScript 文件完全省略其他入口点。