Compartilhar via


Como exibir o status da impressora em um aplicativo de dispositivo UWP

No Windows 8.1, os usuários podem verificar o status da impressora na interface do usuário moderna de um aplicativo de dispositivo UWP. Este tópico usa a versão C# do exemplo Configurações de impressão e notificações de impressão para demonstrar como consultar o status da impressora e exibi-lo. Para saber mais sobre aplicativos de dispositivo UWP em geral, consulte Conhecer os aplicativos de dispositivo UWP.

A versão C# do exemplo Configurações de impressão e notificações de impressão usa a página InkLevel.xaml para demonstrar como obter o status da impressora (neste caso, o nível de tinta) e exibi-lo. Uma classe auxiliar de impressão é usada para criar um contexto de dispositivo (IPrinterExtensionContext) e executar as consultas de dispositivo. O arquivo PrinterHelperClass.cs está no projeto DeviceAppForPrintersLibrary e usa APIs definidas no projeto PrinterExtensionLibrary. A biblioteca de extensão de impressora fornece uma maneira conveniente de acessar as interfaces de extensão de impressora do driver de impressão v4. Para obter mais informações, consulte Visão geral da biblioteca de extensões de impressora.

Observação

Os exemplos de código mostrados neste tópico são baseados na versão C# do exemplo Configurações de impressão e notificações de impressão. Este exemplo também está disponível em JavaScript e C++. Como o C++ pode acessar o COM diretamente, a versão de C++ do exemplo não inclui projetos de biblioteca de códigos. Baixe os exemplos para ver as versões mais recentes do código.

Pré-requisitos

Antes de começar:

  1. Verifique se a impressora está instalada usando um driver de impressão v4. Para obter mais informações, consulte Desenvolvendo drivers de impressão v4.

  2. Obtenha a configuração de seu computador de desenvolvimento. Consulte Introdução para obter informações sobre como baixar as ferramentas e criar uma conta de desenvolvedor.

  3. Associar seu aplicativo à loja. Consulte Etapa 1: Criar um aplicativo de dispositivo UWP para obter informações sobre isso.

  4. Crie metadados de dispositivo para sua impressora que os associem ao seu aplicativo. Consulte Etapa 2: Criar metadados do dispositivo para saber mais sobre isso.

  5. Se você estiver escrevendo seu aplicativo com C# ou JavaScript, adicione os projetos PrinterExtensionLibrary e DeviceAppForPrintersLibrary à sua solução de aplicativo de dispositivo UWP. Você pode encontrar cada um desses projetos no exemplo Configurações de impressão e notificações de impressão.

    Observação

    Como o C++ pode acessar o COM diretamente, os aplicativos C++ não requerem uma biblioteca separada para trabalhar com o contexto do dispositivo de impressora baseado em COM.

Etapa 1: Encontrar a impressora

Para que um contexto de dispositivo possa ser criado, o aplicativo precisa determinar a ID do dispositivo da impressora. Para fazer isso, o exemplo usa o método EnumerateAssociatedPrinters para pesquisar todas as impressoras conectadas ao PC. Em seguida, ele verifica o contêiner de cada impressora e procura uma associação, comparando a propriedade PackageFamilyName de cada contêiner.

Observação

O System.Devices.AppPackageFamilyName para dispositivos associados ao seu aplicativo pode ser encontrado na guia Empacotamento no Designer de Manifesto no Microsoft Visual Studio.

Este exemplo mostra o método EnumerateAssociatedPrinters do arquivo 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());
    }
}

O método FindAssociation, chamado por EnumerateAssociatedPrinters, verifica se uma impressora está associada ao aplicativo atual. Em outras palavras, esse método verifica se o aplicativo é um aplicativo de dispositivo UWP. Essa associação existe quando o aplicativo e a impressora são definidos nos metadados do dispositivo no computador local.

Este exemplo mostra o método FindAssociation do arquivo 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 uma associação é encontrada, o método FindAssociation usa o método AddToList para adicionar a ID do dispositivo a uma lista de IDs de dispositivos associados. Esses IDs são armazenados em um ComboBox denominado AssociatedPrinters.

Este exemplo mostra o método AddToList do arquivo 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;
    }
}

Etapa 2: Exibir o status

O método GetInkStatus usa um padrão assíncrono baseado em evento para solicitar informações da impressora. Esse método usa uma ID de dispositivo associada para obter um contexto de dispositivo que pode ser usado para obter o status do dispositivo. A chamada para o método printHelper.SendInkLevelQuery() inicia a consulta do dispositivo. Quando a resposta é retornada, o método OnInkLevelReceived é chamado e a interface do usuário é atualizada.

Observação

Este exemplo de C# segue um padrão diferente do exemplo de JavaScript, porque o C# permite que você envie um dispatcher para o arquivo PrintHelperClass, de forma que ele possa postar as mensagens de evento de volta no thread da interface do usuário.

Este exemplo mostra os métodos GetInkStatus e OnInkLevelReceived do arquivo 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;
}

A classe auxiliar de impressão se encarrega de enviar a consulta Bidi para o dispositivo e de receber a resposta.

Este exemplo mostra o método SendInkLevelQuery, e outros, do arquivo PrintHelperClass.cs. Apenas alguns dos métodos de classe auxiliar de impressão são mostrados aqui. Baixe o exemplo Configurações de impressão e notificações de impressão para ver o código 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");
    }
}

Testando

Para que você possa testar seu aplicativo de dispositivo UWP, ele deve estar vinculado à impressora usando metadados do dispositivo.

Você precisa de uma cópia do pacote de metadados do dispositivo para sua impressora, a fim de adicionar as informações do aplicativo do dispositivo a ele. Se você não tiver metadados de dispositivo, poderá criá-los usando o Assistente de Criação de Metadados de Dispositivo, conforme descrito no tópico Etapa 2: Criar metadados de dispositivo para seu aplicativo de dispositivo UWP.

Observação

Para usar o Assistente de Criação de Metadados de Dispositivo, você deve instalar o Microsoft Visual Studio Professional, o Microsoft Visual Studio Ultimate ou o SDK autônomo para Windows 8.1, antes de concluir as etapas neste tópico. A instalação do Microsoft Visual Studio Express para Windows instala uma versão do SDK que não inclui o assistente.

As etapas a seguir criam seu aplicativo e instalam os metadados do dispositivo.

  1. Habilite a assinatura para teste.

    1. Inicie o Assistente de Criação de Metadados de Dispositivo em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes DeviceMetadataWizard.exe

    2. No menu Ferramentas, selecione Habilitar Assinatura para Teste.

  2. Reinicialize o computador

  3. Crie a solução abrindo o arquivo de solução (.sln). Pressione F7 ou vá para Criar->Criar Solução no menu superior depois que o exemplo foi carregado.

  4. Desconecte e desinstale a impressora. Esta etapa será requerida para que o Windows leia os metadados de dispositivo atualizados na próxima vez que o dispositivo for detectado.

  5. Edite e salve o metadados do dispositivo. Para vincular o aplicativo de dispositivo ao seu dispositivo, você deve associá-lo ao seu dispositivo.

    Observação

    Se você ainda não criou os metadados do dispositivo, consulte Etapa 2: Criar metadados de dispositivo para seu aplicativo de dispositivo UWP.

    1. Se o Assistente de Criação de Metadados de Dispositivo ainda não estiver aberto, inicie-o em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes em DeviceMetadataWizard.exe.

    2. Clique em Editar metadados do dispositivo. Isso permitirá que você edite o pacote de metadados do dispositivo existente.

    3. Na caixa de diálogo Abrir, localize o pacote de metadados do dispositivo associado ao seu aplicativo de dispositivo UWP. (Ele tem uma extensão de arquivo devicemetadata-ms.)

    4. Na página Especificar informações do aplicativo de dispositivo UWP, insira as informações do aplicativo da Microsoft Store na caixa Aplicativo de dispositivo UWP. Clique em Importar arquivo de manifesto do aplicativo UWP para inserir automaticamente o Nome do pacote, o Nome do editor e a ID de aplicativo UWP.

    5. Se seu aplicativo estiver registrado para receber notificações de impressora, preencha a caixa Manipuladores de notificação. Em ID do evento, insira o nome do manipulador de eventos de impressão. Em Ativo de Evento, insira o nome do arquivo em que esse código reside.

    6. Quando terminar, clique em Avançar até chegar à página Concluir.

    7. Na página Revisar o pacote de metadados do dispositivo, verifique se todas as configurações estão corretas e marque a caixa de seleção Copiar o pacote de metadados de dispositivo para o repositório de metadados no computador local. Em seguida, clique em Salvar.

  6. Reconecte a impressora para que o Windows leia os metadados atualizados do dispositivo quando ele está conectado.

Solução de problemas

Problema: não é possível localizar a impressora ao enumerar dispositivos associados ao aplicativo

Se a sua impressora não for encontrada ao enumerar as impressoras associadas:

  • Causa possível: a assinatura de teste não está ativada. Consulte a seção Depuração neste tópico para obter informações sobre como ativá-la.

  • Causa possível: o aplicativo não está consultando o Nome da Família de Pacotes correto. Verifique o Nome da Família de Pacotes em seu código. Abra package.appxmanifest no Microsoft Visual Studio e verifique se o nome da família de pacotes que você está consultando corresponde ao especificado na guia Empacotamento, no campo Nome da Família de Pacotes.

  • Causa possível: os metadados do dispositivo não estão associados ao Nome da Família de Pacotes. Use o Assistente de Criação de Metadados de Dispositivo para abrir os metadados do dispositivo e verificar o nome da família de pacotes. Inicie o assistente em %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86, clicando duas vezes em DeviceMetadataWizard.exe.

Problema: encontrou a impressora associada ao aplicativo, mas não pode consultar informações Bidi

Se sua impressora foi encontrada ao enumerar as impressoras associadas, mas uma consulta Bidi retorna um erro...

  • Causa possível: nome da família de pacotes incorreto. Verifique o Nome da Família de Pacotes em seu código. Abra package.appxmanifest no Visual Studio e verifique se o nome da família de pacotes que você está consultando corresponde ao especificado na guia Empacotamento, no campo Nome da Família de Pacotes.

  • Causa possível: a impressora foi instalada usando uma impressora v3, em vez de uma impressora v4. Para ver qual versão está instalada, abra o PowerShell e digite o seguinte comando:

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

Desenvolvendo drivers de impressão v4

Interfaces de extensão de impressora (driver de impressão v4)

Comunicação bidirecional

Introdução aos aplicativos UWP

Criar um aplicativo de dispositivo UWP (guia passo a passo)

Criar metadados de dispositivo para um aplicativo de dispositivo UWP (guia passo a passo)