Condividi tramite


Come visualizzare lo stato della stampante in un'app per dispositivi UWP

In Windows 8.1 gli utenti possono controllare lo stato della stampante dall'interfaccia utente moderna di un'app per dispositivi UWP. In questo argomento viene usata la versione C# delle impostazioni di stampa e dell'esempio di notifiche di stampa per illustrare come eseguire una query sullo stato della stampante e visualizzarla. Per altre informazioni sulle app per dispositivi UWP in generale, vedi Soddisfare le app per dispositivi UWP.

La versione C# delle impostazioni di stampa e dell'esempio di notifiche di stampa usa la pagina InkLevel.xaml per illustrare come ottenere lo stato della stampante (in questo caso, il livello input penna) e visualizzarlo. Una classe helper di stampa viene usata per creare un contesto di dispositivo (IPrinterExtensionContext) ed eseguire le query del dispositivo. Il file PrinterHelperClass.cs si trova nel progetto DeviceAppForPrintersLibrary e usa le API definite nel progetto PrinterExtensionLibrary . La libreria di estensioni della stampante offre un modo pratico per accedere alle interfacce di estensione della stampante del driver di stampa v4. Per altre info, vedi Panoramica della libreria di estensioni della stampante.

Nota

Gli esempi di codice illustrati in questo argomento si basano sulla versione C# delle impostazioni di stampa e sull'esempio di notifiche di stampa. Questo esempio è disponibile anche in JavaScript e C++. Si noti che poiché C++ può accedere direttamente a COM, la versione C++ dell'esempio non include progetti di libreria di codice. Scaricare gli esempi per visualizzare le versioni più recenti del codice.

Prerequisiti

Prima di iniziare:

  1. Assicurarsi che la stampante sia installata usando un driver di stampa v4. Per altre informazioni, vedi Sviluppo di driver di stampa v4.

  2. Configurare il PC di sviluppo. Vedi Introduzione per informazioni sul download degli strumenti e sulla creazione di un account per sviluppatore.

  3. Associare l'app allo Store. Per informazioni su questo, vedi Passaggio 1: Creare un'app per dispositivi UWP.

  4. Creare i metadati del dispositivo per la stampante che la associa all'app. Per altre informazioni, vedere Passaggio 2: Creare i metadati del dispositivo.

  5. Se stai scrivendo la tua app con C# o JavaScript, aggiungi i progetti PrinterExtensionLibrary e DeviceAppForPrintersLibrary alla soluzione di app per dispositivi UWP. È possibile trovare ognuno di questi progetti nell'esempio Di impostazioni di stampa e notifiche di stampa.

    Nota

    Poiché C++ può accedere direttamente a COM, le app C++ non richiedono una libreria separata per funzionare con il contesto di dispositivo della stampante basato su COM.

Passaggio 1: Trovare la stampante

Prima di poter creare un contesto di dispositivo, l'app deve determinare l'ID dispositivo della stampante. A tale scopo, l'esempio usa il EnumerateAssociatedPrinters metodo per cercare tutte le stampanti collegate al PC. Controlla quindi il contenitore per ogni stampante e cerca un'associazione confrontando la proprietà PackageFamilyName di ogni contenitore.

Nota

System.Devices.AppPackageFamilyName per i dispositivi associati all'app sono disponibili nella scheda Creazione pacchetti di Progettazione manifesto in Microsoft Visual Studio.

Questo esempio mostra il EnumerateAssociatedPrinters metodo del file InkLevel.xaml.cs :

async void EnumerateAssociatedPrinters(object sender, RoutedEventArgs e)
{
    // Reset output text and associated printer array.
    AssociatedPrinters.Items.Clear();
    BidiOutput.Text = "";

    // GUID string for printers.
    string printerInterfaceClass = "{0ecef634-6ef0-472a-8085-5ad023ecbccd}";
    string selector = "System.Devices.InterfaceClassGuid:=\"" + printerInterfaceClass + "\"";

    // By default, FindAllAsync does not return the containerId for the device it queries.
    // We have to add it as an additional property to retrieve. 
    string containerIdField = "System.Devices.ContainerId";
    string[] propertiesToRetrieve = new string[] { containerIdField };

    // Asynchronously find all printer devices.
    DeviceInformationCollection deviceInfoCollection = await DeviceInformation.FindAllAsync(selector, propertiesToRetrieve);

    // For each printer device returned, check if it is associated with the current app.
    for (int i = 0; i < deviceInfoCollection.Count; i++)
    {
        DeviceInformation deviceInfo = deviceInfoCollection[i];
        FindAssociation(deviceInfo, deviceInfo.Properties[containerIdField].ToString());
    }
}

Il FindAssociation metodo , chiamato da EnumerateAssociatedPrinters, controlla se una stampante è associata all'applicazione corrente. In altre parole, questo metodo controlla se l'app è un'app per dispositivi UWP. Questa associazione esiste quando l'app e la stampante sono definite nei metadati del dispositivo nel PC locale.

Questo esempio mostra il FindAssociation metodo del file InkLevel.xaml.cs :

async void FindAssociation(DeviceInformation deviceInfo, string containerId)
{

    // Specifically telling CreateFromIdAsync to retrieve the AppPackageFamilyName. 
    string packageFamilyName = "System.Devices.AppPackageFamilyName";
    string[] containerPropertiesToGet = new string[] { packageFamilyName };

    // CreateFromIdAsync needs braces on the containerId string.
    string containerIdwithBraces = "{" + containerId + "}";

    // Asynchronously getting the container information of the printer.
    PnpObject containerInfo = await PnpObject.CreateFromIdAsync(PnpObjectType.DeviceContainer, containerIdwithBraces, containerPropertiesToGet);

    // Printers could be associated with other device apps, only the ones with package family name
    // matching this app's is associated with this app. The packageFamilyName for this app will be found in this app's packagemanifest
    string appPackageFamilyName = "Microsoft.SDKSamples.DeviceAppForPrinters.CS_8wekyb3d8bbwe";
    var prop = containerInfo.Properties;

    // If the packageFamilyName of the printer container matches the one for this app, the printer is associated with this app.
    string[] packageFamilyNameList = (string[])prop[packageFamilyName];
    if (packageFamilyNameList != null)
    {
        for (int j = 0; j < packageFamilyNameList.Length; j++)
        {
            if (packageFamilyNameList[j].Equals(appPackageFamilyName))
            {
                AddToList(deviceInfo);
            }
        }
    }
}

Quando viene trovata un'associazione, il FindAssociation metodo usa il AddToList metodo per aggiungere l'ID dispositivo a un elenco di ID dispositivo associati. Questi ID vengono archiviati in un controllo ComboBox denominato AssociatedPrinters.

Questo esempio mostra il AddToList metodo del file InkLevel.xaml.cs :

void AddToList(DeviceInformation deviceInfo)
{
    // Creating a new display item so the user sees the friendly name instead of the interfaceId.
    ComboBoxItem item = new ComboBoxItem();
    item.Content = deviceInfo.Properties["System.ItemNameDisplay"] as string;
    item.DataContext = deviceInfo.Id;
    AssociatedPrinters.Items.Add(item);

    // If this is the first printer to be added to the combo box, select it.
    if (AssociatedPrinters.Items.Count == 1)
    {
        AssociatedPrinters.SelectedIndex = 0;
    }
}

Passaggio 2: Visualizzare lo stato

Il GetInkStatus metodo usa un modello asincrono basato su eventi per richiedere informazioni dalla stampante. Questo metodo usa un ID dispositivo associato per ottenere un contesto di dispositivo che può essere usato per ottenere lo stato del dispositivo. La chiamata al printHelper.SendInkLevelQuery() metodo avvia la query del dispositivo. Quando la risposta viene restituita, viene chiamato il OnInkLevelReceived metodo e l'interfaccia utente viene aggiornata.

Nota

Questo esempio C# segue un modello diverso rispetto all'esempio JavaScript, perché C# consente di inviare un dispatcher a PrintHelperClass in modo che possa pubblicare nuovamente i messaggi dell'evento nel thread dell'interfaccia utente.

Questo esempio mostra i GetInkStatus metodi e OnInkLevelReceived del file InkLevel.xaml.cs :

void GetInkStatus(object sender, RoutedEventArgs e)
{
    if (AssociatedPrinters.Items.Count > 0)
    {
        // Get the printer that the user has selected to query.
        ComboBoxItem selectedItem = AssociatedPrinters.SelectedItem as ComboBoxItem;

        // The interfaceId is retrieved from the detail field.
        string interfaceId = selectedItem.DataContext as string;

        try
        {
            // Unsubscribe existing ink level event handler, if any.
            if (printHelper != null)
            {
                printHelper.OnInkLevelReceived -= OnInkLevelReceived;
                printHelper = null;
            }

            object context = Windows.Devices.Printers.Extensions.PrintExtensionContext.FromDeviceId(interfaceId);printHelper.SendInkLevelQuery()

            // Use the PrinterHelperClass to retrieve the bidi data and display it.
            printHelper = new PrintHelperClass(context);
            try
            {
                printHelper.OnInkLevelReceived += OnInkLevelReceived;
                printHelper.SendInkLevelQuery();

                rootPage.NotifyUser("Ink level query successful", NotifyType.StatusMessage);
            }
            catch (Exception)
            {
                rootPage.NotifyUser("Ink level query unsuccessful", NotifyType.ErrorMessage);
            }
        }
        catch (Exception)
        {
            rootPage.NotifyUser("Error retrieving PrinterExtensionContext from InterfaceId", NotifyType.ErrorMessage);
        }
    }
}

private void OnInkLevelReceived(object sender, string response)
{
    BidiOutput.Text = response;
}

La classe helper di stampa si occupa dell'invio della query Bidi al dispositivo e della ricezione della risposta.

In questo esempio viene illustrato il SendInkLevelQuery metodo e altri dal file PrintHelperClass.cs . Si noti che solo alcuni dei metodi della classe helper di stampa sono visualizzati qui. Scaricare l'esempio di impostazioni di stampa e notifiche di stampa per visualizzare il codice completo.

public void SendInkLevelQuery()
{
    printerQueue.OnBidiResponseReceived += OnBidiResponseReceived;

    // Send the query.
    string queryString = "\\Printer.Consumables";
    printerQueue.SendBidiQuery(queryString);
}

private void OnBidiResponseReceived(object sender, PrinterQueueEventArgs responseArguments)
{
    // Invoke the ink level event with appropriate data.
    dispatcher.RunAsync(
        Windows.UI.Core.CoreDispatcherPriority.Normal,
        () =>
        {
            OnInkLevelReceived(sender, ParseResponse(responseArguments));
        });
}

private string ParseResponse(PrinterQueueEventArgs responseArguments)
{
    if (responseArguments.StatusHResult == (int)HRESULT.S_OK)
        return responseArguments.Response;
    else
        return InvalidHResult(responseArguments.StatusHResult);
}

private string InvalidHResult(int result)
{
    switch (result)
    {
        case unchecked((int)HRESULT.E_INVALIDARG):
            return "Invalid Arguments";
        case unchecked((int)HRESULT.E_OUTOFMEMORY):
            return "Out of Memory";
        case unchecked((int)HRESULT.ERROR_NOT_FOUND):
            return "Not found";
        case (int)HRESULT.S_FALSE:
            return "False";
        case (int)HRESULT.S_PT_NO_CONFLICT:
            return "PT No Conflict";
        default:
            return "Undefined status: 0x" + result.ToString("X");
    }
}

Test in corso

Prima di poter testare l'app per dispositivi UWP, deve essere collegata alla stampante usando i metadati del dispositivo.

È necessaria una copia del pacchetto di metadati del dispositivo per la stampante per aggiungere le informazioni sull'app del dispositivo. Se non hai metadati del dispositivo, puoi compilarlo usando la Creazione guidata metadati dispositivo come descritto nell'argomento Passaggio 2: Creare i metadati del dispositivo per l'app per dispositivi UWP.

Nota

Per usare la Creazione guidata metadati dispositivo, è necessario installare Microsoft Visual Studio Professional, Microsoft Visual Studio Ultimate o l'SDK autonomo per Windows 8.1, prima di completare i passaggi descritti in questo argomento. L'installazione di Microsoft Visual Studio Express per Windows installa una versione dell'SDK che non include la procedura guidata.

La procedura seguente consente di compilare l'app e installare i metadati del dispositivo.

  1. Abilitare la firma di test.

    1. Avviare la Creazione guidata metadati dispositivo da %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 facendo doppio clic su DeviceMetadataWizard.exe

    2. Scegliere Abilita firma test dal menu Strumenti.

  2. Riavviare il computer

  3. Compilare la soluzione aprendo il file della soluzione (.sln). Premere F7 o passare a Compila soluzione> dal menu in alto dopo il caricamento dell'esempio.

  4. Disconnettere e disinstallare la stampante. Questo passaggio è obbligatorio in modo che Windows leggerà i metadati aggiornati del dispositivo alla successiva individuazione del dispositivo.

  5. Modificare e salvare i metadati del dispositivo. Per collegare l'app del dispositivo al dispositivo, devi associare l'app per dispositivo al dispositivo.

    Nota

    Se non hai ancora creato i metadati del dispositivo, vedi Passaggio 2: Creare metadati del dispositivo per l'app per dispositivi UWP.

    1. Se la Creazione guidata metadati dispositivo non è ancora aperta, avviarla da %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 facendo doppio clic su DeviceMetadataWizard.exe.

    2. Fare clic su Modifica metadati dispositivo. In questo modo sarà possibile modificare il pacchetto di metadati del dispositivo esistente.

    3. Nella finestra di dialogo Apri individuare il pacchetto di metadati del dispositivo associato all'app per dispositivi UWP. Ha un'estensione di file devicemetadata-ms .

    4. Nella pagina Specificare le informazioni sull'app per dispositivi UWP immettere le informazioni sull'app di Microsoft Store nella casella app per dispositivi UWP. Fare clic su Importa file manifesto dell'app UWP per immettere automaticamente il nome del pacchetto, il nome dell'editore e l'ID app UWP.

    5. Se l'app sta registrando per le notifiche della stampante, compilare la casella Gestori di notifica. In ID evento immettere il nome del gestore eventi di stampa. In Asset evento immettere il nome del file in cui risiede il codice.

    6. Al termine, fare clic su Avanti finché non si arriva alla pagina Fine .

    7. Nella pagina Rivedi il pacchetto di metadati del dispositivo verificare che tutte le impostazioni siano corrette e selezionare la casella di controllo Copia il pacchetto di metadati del dispositivo nell'archivio metadati nel computer locale. Fare clic su Save (Salva).

  6. Riconnettere la stampante in modo che Windows legga i metadati aggiornati del dispositivo quando il dispositivo è connesso.

Risoluzione dei problemi

Problema: Impossibile trovare la stampante durante l'enumerazione dei dispositivi associati all'app

Se la stampante non viene trovata durante l'enumerazione delle stampanti associate:

  • Possibile causa: la firma del test non è attivata. Per informazioni sull'attivazione, vedi la sezione Debug in questo argomento.

  • Possibile causa: l'app non esegue query sul nome della famiglia di pacchetti corretto. Controllare il nome della famiglia di pacchetti nel codice. Aprire package.appxmanifest in Microsoft Visual Studio e assicurarsi che il nome della famiglia di pacchetti su cui si sta eseguendo una query corrisponda a quello nella scheda Creazione pacchetti, nel campo Nome famiglia di pacchetti.

  • Possibile causa: i metadati del dispositivo non sono associati al nome della famiglia di pacchetti. Usare la Creazione guidata metadati dispositivo per aprire i metadati del dispositivo e controllare il nome della famiglia di pacchetti. Avviare la procedura guidata da %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86 facendo doppio clic su DeviceMetadataWizard.exe.

Problema: stampante trovata associata all'app, ma non è possibile eseguire query sulle informazioni bidi

Se la stampante è stata trovata durante l'enumerazione delle stampanti associate, ma una query Bidi restituisce un errore...

  • Possibile causa: nome della famiglia di pacchetti errato. Controllare il nome della famiglia di pacchetti nel codice. Aprire package.appxmanifest in Visual Studio e assicurarsi che il nome della famiglia di pacchetti su cui si sta eseguendo una query corrisponda a quello nella scheda Creazione pacchetti nel campo Nome famiglia di pacchetti.

  • Possibile causa: la stampante è stata installata usando una stampante v3, anziché una stampante v4. Per visualizzare la versione installata, aprire PowerShell e digitare il comando seguente:

    get-printer | Select Name, {(get-printerdriver -Name $_.DriverName).MajorVersion}
    

Sviluppo di driver di stampa v4

Interfacce di estensione della stampante (driver di stampa v4)

Comunicazioni bidirezionali

Introduzione alle app UWP

Creare un'app per dispositivi UWP (guida dettagliata)

Creare metadati del dispositivo per un'app per dispositivi UWP (guida dettagliata)