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
開始之前:
請確定您的印表機是使用 v4 印表驅動程式安裝。 如需詳細資訊,請參閱 開發 v4 列印驅動程式。
設定好您的開發電腦。 See Getting started for info about downloading the tools and creating a developer account.
將您的應用程式與市集產生關聯。 如需相關信息,請參閱 建立 UWP 裝置應用程式。
為您的印表機建立裝置元數據,使其與您的應用程式產生關聯。 如需詳細資訊,請參閱 建立裝置元數據。
建置應用程式主頁面的UI。 所有UWP裝置應用程式都可以從 [開始] 啟動,其中會顯示全螢幕。 利用 \[開始\] 體驗,以符合您裝置特定品牌和功能的方式強調您的產品或服務。 它可以使用的UI控制件類型沒有任何特殊限制。 若要開始設計全螢幕體驗,請參閱 Microsoft Store 設計原則。
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 物件清單,其中包含每個印表機的名稱和裝置標識符。
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 版本。
下列步驟會建置您的應用程式並安裝裝置元數據。
啟用測試簽署。
按兩下 DeviceMetadataWizard.exe,從 %ProgramFiles[x86]%\Windows Kits\8.1\bin\x86 啟動 裝置元數據撰寫精靈
From the Tools menu, select Enable Test Signing.
重新啟動電腦
開啟方案 (.sln) 檔案來建置方案。 按 F7,或在載入範例之後,從頂端功能表移至 [建>置方案 ]。
中斷連線並卸載印表機。 需要此步驟,Windows 會在下次偵測到裝置時讀取更新的裝置元數據。
編輯並儲存裝置元數據。 若要將裝置應用程式連結至您的裝置,您必須將裝置應用程式與裝置產生關聯。 如果您尚未建立裝置元數據,請參閱 建立 UWP 裝置應用程式的裝置元數據。
如果裝置元數據撰寫精靈尚未開啟,請按兩下DeviceMetadataWizard.exe,從 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 啟動。
選取 [編輯裝置元數據]。 此選項可讓您編輯現有的裝置元資料套件。
In the Open dialog box, locate the device metadata package associated with your UWP device app. (It has a devicemetadata-ms file extension.)
在 [指定 UWP 裝置應用程式資訊] 頁面上,於 [UWP 裝置應用程式] 方塊中輸入 Microsoft 市集應用程式資訊。 選取 [匯入 UWP 應用程式指令清單檔案 ],以自動輸入 套件名稱、 發行者名稱和UWP 應用程式識別碼。
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.
When you're done, select Next until you get to the Finish page.
在 [檢閱裝置元數據套件] 頁面上,確定所有設定都正確無誤,然後選取 [將裝置元數據套件複製到本機計算機上的元數據存放區 複選框。 Then select Save.
重新連線印表機,讓 Windows 在裝置連線時讀取更新的裝置元數據。