如何在 UWP 设备应用中执行打印机维护

Important

设备元数据已弃用,并将在 Windows 的将来版本中删除。 有关替代功能的信息,请参阅驱动程序包容器元数据

在 Windows 8.1 中,UWP 设备应用可以执行打印机维护,例如对齐打印头和清洁喷头。 本文使用 打印作业管理和打印机维护 示例的 C# 版本来演示如何使用双向通信(Bidi)来执行此类设备维护。 若要了解有关 UWP 设备应用的一般详细信息,请参阅 UWP 设备应用简介

打印作业管理和打印机维护示例的 C# 版本演示了使用 DeviceAppForPrinters2 项目中DeviceMaintenance.xaml.cs文件的打印机维护。 To work with Bidi, the sample uses the printer extension library in the PrinterExtensionLibrary project. 打印机扩展库提供了一种访问 v4 打印驱动程序的打印机扩展接口的便捷方法。 有关详细信息,请参阅 打印机扩展库概述

Note

本文中所示的代码示例基于 打印作业管理和打印机维护 示例的 C# 版本。 此示例在 JavaScript 和 C++中也可用。 由于C++可以直接访问 COM,因此示例C++版本不包括代码库项目。 下载示例以查看最新版本的代码。

Printer maintenance

Windows 8.1 introduces new printer extension interfaces in the v4 printer driver that you can use for implementing device maintenance: IPrinterBidiSetRequestCallback, IPrinterExtensionAsyncOperation , and IPrinterQueue2. 这些接口可以异步将 Bidi 请求发送到端口监视器,以便将其转换为设备和协议特定的命令,然后将其发送到打印机。 有关详细信息,请参阅设备维护(v4 打印机驱动程序)。

Tip

C# 和 JavaScript 应用不能直接使用 COM API。 如果要编写 C# 或 JavaScript UWP 设备应用,请使用打印机扩展库访问这些接口(如本文所示)。

Prerequisites

准备工作:

  1. 请确保使用 v4 打印驱动程序安装打印机。 有关详细信息,请参阅 开发 v4 打印驱动程序

  2. 设置开发电脑。 See Getting started for info about downloading the tools and creating a developer account.

  3. 将应用与应用商店相关联。 有关该应用的信息,请参阅 “创建 UWP 设备应用 ”。

  4. 为将它与应用关联的打印机创建设备元数据。 有关详细信息,请参阅 “创建设备元数据”。

  5. 为应用的主页生成 UI。 可以从“开始”启动启动所有 UWP 设备应用,其中显示全屏。 使用“开始”体验以与设备的特定品牌和功能匹配的方式突出显示产品或服务。 它可以使用的 UI 控件类型没有特殊限制。 若要开始设计全屏体验,请参阅 Microsoft应用商店设计原则

  6. If you're writing your app with C# or JavaScript, add the PrinterExtensionLibrary project to your UWP device app solution. 可以在 打印作业管理和打印机维护 示例中找到此项目。

Note

由于C++可以直接访问 COM,C++应用不需要单独的库来处理基于 COM 的打印机设备上下文。

步骤 1:准备 Bidi 请求

设备维护接口要求 Bidi 请求是字符串形式的 XML 数据。 无论在应用中哪个位置都有意义,都可以构造 Bidi 请求。 例如,可以将 Bidi 请求保存为字符串常量,或根据用户输入动态创建它们。 打印作业管理和打印机维护示例在方法中OnNavigatedTo构造默认请求。 For more info about Bidi, see Bidirectional Communications.

This example is from the OnNavigatedTo method of the DeviceMaintenance.xaml.cs file.

string defaultBidiQuery =
    "<bidi:Set xmlns:bidi=\"http://schemas.microsoft.com/windows/2005/03/printing/bidi\">\r\n" +
    "    <Query schema='\\Printer.Maintenance:CleanHead'>\r\n" +
    "        <BIDI_BOOL>false</BIDI_BOOL>\r\n" +
    "    </Query>\r\n" +
    "</bidi:Set>";

步骤 2:查找打印机

应用必须先找到打印机,然后应用才能将命令发送到打印机。 为此, 打印作业管理和打印机维护 示例包括一个名为 PrinterEnumeration (在 PrinterEnumeration.cs 文件中)的类。 此类通过设备元数据查找与应用关联的所有打印机,并返回一个对象列表 PrinterInfo ,其中包含每个打印机的名称和设备 ID。

This example is from the EnumeratePrinters_Click method of the DeviceMaintenance.xaml.cs file. 它演示示例如何使用 PrinterEnumeration 该类获取关联的打印机列表。

private async void EnumeratePrinters_Click(object sender, RoutedEventArgs e)
{
    try
    {
        rootPage.NotifyUser("Enumerating printers. Please wait", NotifyType.StatusMessage);

        // Retrieve the running app's package family name, and enumerate associated printers.
        string currentPackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

        // Enumerate associated printers.
        PrinterEnumeration pe = new PrinterEnumeration(currentPackageFamilyName);
        List<PrinterInfo> associatedPrinters = await pe.EnumeratePrintersAsync();

        // Update the data binding source on the combo box that displays the list of printers.
        PrinterComboBox.ItemsSource = associatedPrinters;
        if (associatedPrinters.Count > 0)
        {
            PrinterComboBox.SelectedIndex = 0;
            rootPage.NotifyUser(associatedPrinters.Count + " printers enumerated", NotifyType.StatusMessage);
        }
        else
        {
            rootPage.NotifyUser(DisplayStrings.NoPrintersEnumerated, NotifyType.ErrorMessage);
        }
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

Tip

For more info about the PrinterEnumeration and PrinterInfo classes, see the PrinterEnumeration.cs file.

步骤 3:发送 Bidi 请求

若要发送 Bidi 请求,设备维护接口需要 Bidi 字符串和回调。 在方法中 SendBidiRequest_Click ,示例首先使用对象 PrinterInfo 创建名为 context 的打印机扩展上下文对象。 然后创建一个 PrinterBidiSetRequestCallback 对象,并添加一个事件处理程序来处理回调 OnBidiResponseReceived 的事件。 最后,打印机扩展上下文 SendBidiSetRequestAsync 的方法用于发送 Bidi 字符串和回调。

This example is from the SendBidiRequest_Click method of the DeviceMaintenance.xaml.cs file.

private void SendBidiRequest_Click(object sender, RoutedEventArgs e)
{
    try
    {
        PrinterInfo queue = (PrinterInfo)PrinterComboBox.SelectedItem;

        // Retrieve a COM IPrinterExtensionContext object, using the static WinRT factory.
        // Then instantiate one "PrinterExtensionContext" object that allows operations on the COM object.
        Object comContext = Windows.Devices.Printers.Extensions.PrintExtensionContext.FromDeviceId(queue.DeviceId);
        PrinterExtensionContext context = new PrinterExtensionContext(comContext);

        // Create an instance of the callback object, and perform an asynchronous 'bidi set' operation.
        PrinterBidiSetRequestCallback callback = new PrinterBidiSetRequestCallback();

        // Add an event handler to the callback object's OnBidiResponseReceived event.
        // The event handler will be invoked once the Bidi response is received.
        callback.OnBidiResponseReceived += OnBidiResponseReceived;

        // Send the Bidi "Set" query asynchronously.
        IPrinterExtensionAsyncOperation operationContext
            = context.Queue.SendBidiSetRequestAsync(BidiQueryInput.Text, callback);

        // The 'operationContext' object can be used to cancel the operation if required.
    }
    catch (Exception exception)
    {
        rootPage.NotifyUser("Caught an exception: " + exception.Message, NotifyType.ErrorMessage);
    }
}

步骤 4:接收 Bidi 响应

当 Bidi “set”作完成时,将调用类型为类型的 PrinterBidiSetRequestCallback回调对象。 此回调负责 HRESULT 响应中的错误处理,然后触发 OnBidiResponseReceived 事件,并通过事件参数发送 Bidi 响应。

This example shows the PrinterBidiSetRequestCallback class definition in the DeviceMaintenance.xaml.cs file.

internal class PrinterBidiSetRequestCallback : IPrinterBidiSetRequestCallback
{
    /// <summary>
    /// This method is invoked when the asynchronous Bidi "Set" operation is completed.
    /// </summary>
    public void Completed(string response, int statusHResult)
    {
        string result;

        if (statusHResult == (int)HRESULT.S_OK)
        {
            result = "The response is \r\n" + response;
        }
        else
        {
            result = "The HRESULT received is: 0x" + statusHResult.ToString("X") + "\r\n" +
                     "No Bidi response was received";
        }

        // Invoke the event handlers when the Bidi response is received.
        OnBidiResponseReceived(null, result);
    }

    /// <summary>
    /// This event will be invoked when the Bidi 'set' response is received.
    /// </summary>
    public event EventHandler<string> OnBidiResponseReceived;
}

然后,Bidi 响应将发送到 OnBidiResponseReceived 方法,该方法 Dispatcher 用于在 UI 线程上显示结果。

This example is from the OnBidiResponseReceived method of the DeviceMaintenance.xaml.cs file.

internal async void OnBidiResponseReceived(object sender, string bidiResponse)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        BidiResponseOutput.Text = bidiResponse;
    });
}

Testing

在测试 UWP 设备应用之前,必须使用设备元数据将其链接到打印机。

需要打印机的设备元数据包的副本,才能将设备应用信息添加到其中。 如果没有设备元数据,可以使用 设备元数据创作向导 生成它,如 UWP 设备应用创建设备元数据一文中所述。

Note

若要使用 设备元数据创作向导,必须先安装 Microsoft Visual Studio Professional、Microsoft Visual Studio Ultimate 或 适用于 Windows 8.1 的独立 SDK,然后才能完成本文中的步骤。 安装 Microsoft Visual Studio Express for Windows 会安装不包含向导的 SDK 版本。

以下步骤生成应用并安装设备元数据。

  1. 启用测试签名。

    1. 通过双击DeviceMetadataWizard.exe,从 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 启动设备元数据创作向导

    2. From the Tools menu, select Enable Test Signing.

  2. 重新启动计算机

  3. 通过打开解决方案(.sln)文件生成解决方案。 按 F7 或在加载示例后从顶部菜单中转到 生成>解决方案

  4. 断开连接并卸载打印机。 此步骤是必需的,以便 Windows 将在下次检测到设备时读取更新的设备元数据。

  5. 编辑和保存设备元数据。 若要将设备应用链接到设备,必须将设备应用与设备相关联。 如果尚未创建设备元数据,请参阅 为 UWP 设备应用创建设备元数据

    1. 如果设备元数据创作向导尚未打开,请双击 DeviceMetadataWizard.exe从%ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 启动它。

    2. 选择 “编辑设备元数据”。 使用此选项可以编辑现有的设备元数据包。

    3. In the Open dialog box, locate the device metadata package associated with your UWP device app. (It has a devicemetadata-ms file extension.)

    4. “指定 UWP 设备应用信息 ”页上,在 “UWP 设备应用 ”框中输入Microsoft应用商店应用信息。 选择 “导入 UWP 应用清单文件 ”以自动输入 包名称发布服务器名称和UWP 应用 ID

    5. If your app is registering for printer notifications, fill out the Notification handlers box. In Event ID, enter the name of the print event handler. In Event Asset, enter the name of the file where that code resides.

    6. When you're done, select Next until you get to the Finish page.

    7. 在“ 查看设备元数据包 ”页上,确保所有设置都正确,并选择“ 将设备元数据包复制到本地计算机上的元数据存储 ”复选框。 Then select Save.

  6. 重新连接打印机,以便 Windows 在设备连接时读取更新的设备元数据。