Compartilhar via


Como examinar remotamente o status das impressoras

A qualquer momento, em empresas médias e grandes, pode haver várias impressoras que não estão funcionando devido a um atolamento de papel, falta de papel ou alguma outra situação problemática. O conjunto avançado de propriedades da impressora expostas nas APIs do Microsoft .NET Framework fornece um meio para executar uma pesquisa rápida dos estados das impressoras.

Exemplo

As principais etapas para criar esse tipo de utilitário são as seguintes.

  1. Obtenha uma lista de todos os servidores de impressão.

  2. Percorra os servidores para consultar suas filas de impressão.

  3. Em cada passagem do loop do servidor, percorra todas as filas do servidor e leia cada propriedade que possa indicar que a fila não está operando.

O código a seguir é uma série de snippets. Para simplificar, este exemplo pressupõe que há uma lista delimitada por CRLF de servidores de impressão. A variável fileOfPrintServers é um objeto StreamReader para esse arquivo. Como cada nome de servidor está em sua própria linha, qualquer chamada de ReadLine obtém o nome do próximo servidor e move o cursor do StreamReaderpara o início da próxima linha.

Dentro do loop externo, o código cria um objeto PrintServer para o servidor de impressão mais recente e especifica que o aplicativo deve ter direitos administrativos para o servidor.

Nota

Se houver muitos servidores, você poderá melhorar o desempenho usando os construtores PrintServer(String, String[], PrintSystemDesiredAccess) que inicializam apenas as propriedades necessárias.

Em seguida, o exemplo usa GetPrintQueues para criar uma coleção de todas as filas do servidor e começa a percorrê-las. Esse loop interno contém uma estrutura de ramificação correspondente às duas maneiras de verificar o status de uma impressora:

Este exemplo demonstra ambos os métodos, portanto, o usuário foi solicitado anteriormente sobre qual método usar e respondeu com "y" se quisesse usar os sinalizadores da propriedade QueueStatus. Veja abaixo os detalhes dos dois métodos.

Por fim, os resultados são apresentados ao usuário.

// Survey queue status for every queue on every print server
System::String^ line;
System::String^ statusReport = "\n\nAny problem states are indicated below:\n\n";
while ((line = fileOfPrintServers->ReadLine()) != nullptr)
{
   System::Printing::PrintServer^ myPS = gcnew System::Printing::PrintServer(line, PrintSystemDesiredAccess::AdministrateServer);
   System::Printing::PrintQueueCollection^ myPrintQueues = myPS->GetPrintQueues();
   statusReport = statusReport + "\n" + line;
   for each (System::Printing::PrintQueue^ pq in myPrintQueues)
   {
      pq->Refresh();
      statusReport = statusReport + "\n\t" + pq->Name + ":";
      if (useAttributesResponse == "y")
      {
         TroubleSpotter::SpotTroubleUsingQueueAttributes(statusReport, pq);
         // TroubleSpotter class is defined in the complete example.
      } else
      {
         TroubleSpotter::SpotTroubleUsingProperties(statusReport, pq);
      }
   }
}
fileOfPrintServers->Close();
Console::WriteLine(statusReport);
Console::WriteLine("\nPress Return to continue.");
Console::ReadLine();
// Survey queue status for every queue on every print server
String line;
String statusReport = "\n\nAny problem states are indicated below:\n\n";
while ((line = fileOfPrintServers.ReadLine()) != null)
 {
     PrintServer myPS = new PrintServer(line, PrintSystemDesiredAccess.AdministrateServer);
     PrintQueueCollection myPrintQueues = myPS.GetPrintQueues();
     statusReport = statusReport + "\n" + line;
     foreach (PrintQueue pq in myPrintQueues)
     {
         pq.Refresh();
         statusReport = statusReport + "\n\t" + pq.Name + ":";
         if (useAttributesResponse == "y")
         {
             TroubleSpotter.SpotTroubleUsingQueueAttributes(ref statusReport, pq);
             // TroubleSpotter class is defined in the complete example.
         }
         else
         {
             TroubleSpotter.SpotTroubleUsingProperties(ref statusReport, pq);
         }
     }// end for each print queue
 }// end while list of print servers is not yet exhausted

fileOfPrintServers.Close();
Console.WriteLine(statusReport);
Console.WriteLine("\nPress Return to continue.");
Console.ReadLine();

' Survey queue status for every queue on every print server
Dim line As String
Dim statusReport As String = vbLf & vbLf & "Any problem states are indicated below:" & vbLf & vbLf
line = fileOfPrintServers.ReadLine()
Do While line IsNot Nothing
     Dim myPS As New PrintServer(line, PrintSystemDesiredAccess.AdministrateServer)
     Dim myPrintQueues As PrintQueueCollection = myPS.GetPrintQueues()
     statusReport = statusReport & vbLf & line
     For Each pq As PrintQueue In myPrintQueues
         pq.Refresh()
         statusReport = statusReport & vbLf & vbTab & pq.Name & ":"
         If useAttributesResponse = "y" Then
             TroubleSpotter.SpotTroubleUsingQueueAttributes(statusReport, pq)
             ' TroubleSpotter class is defined in the complete example.
         Else
             TroubleSpotter.SpotTroubleUsingProperties(statusReport, pq)
         End If

     Next pq ' end for each print queue

    line = fileOfPrintServers.ReadLine()
Loop ' end while list of print servers is not yet exhausted

fileOfPrintServers.Close()
Console.WriteLine(statusReport)
Console.WriteLine(vbLf & "Press Return to continue.")
Console.ReadLine()

Para verificar o status da impressora usando os sinalizadores da propriedade QueueStatus, verifique cada sinalizador relevante para ver se ele está definido. A maneira padrão de ver se um bit está definido em um conjunto de sinalizadores de bits é executar uma operação AND lógica com o conjunto de sinalizadores como um operando e o próprio sinalizador como o outro. Como o sinalizador em si tem apenas um bit definido, o resultado do AND lógico é que, no máximo, esse mesmo bit está definido. Para descobrir se ele é ou não, basta comparar o resultado do AND lógico com o próprio sinalizador. Para obter mais informações, consulte PrintQueueStatus, o operador & (referência em C#)e FlagsAttribute.

Para cada atributo cujo bit está definido, o código adiciona um aviso ao relatório final que será apresentado ao usuário. (O método ReportAvailabilityAtThisTime, que é chamado no final do código, será discutido abaixo.)

internal: 
   // Check for possible trouble states of a printer using the flags of the QueueStatus property
   static void SpotTroubleUsingQueueAttributes (System::String^% statusReport, System::Printing::PrintQueue^ pq) 
   {
      if ((pq->QueueStatus & PrintQueueStatus::PaperProblem) == PrintQueueStatus::PaperProblem)
      {
         statusReport = statusReport + "Has a paper problem. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::NoToner) == PrintQueueStatus::NoToner)
      {
         statusReport = statusReport + "Is out of toner. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::DoorOpen) == PrintQueueStatus::DoorOpen)
      {
         statusReport = statusReport + "Has an open door. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::Error) == PrintQueueStatus::Error)
      {
         statusReport = statusReport + "Is in an error state. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::NotAvailable) == PrintQueueStatus::NotAvailable)
      {
         statusReport = statusReport + "Is not available. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::Offline) == PrintQueueStatus::Offline)
      {
         statusReport = statusReport + "Is off line. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::OutOfMemory) == PrintQueueStatus::OutOfMemory)
      {
         statusReport = statusReport + "Is out of memory. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::PaperOut) == PrintQueueStatus::PaperOut)
      {
         statusReport = statusReport + "Is out of paper. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::OutputBinFull) == PrintQueueStatus::OutputBinFull)
      {
         statusReport = statusReport + "Has a full output bin. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::PaperJam) == PrintQueueStatus::PaperJam)
      {
         statusReport = statusReport + "Has a paper jam. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::Paused) == PrintQueueStatus::Paused)
      {
         statusReport = statusReport + "Is paused. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::TonerLow) == PrintQueueStatus::TonerLow)
      {
         statusReport = statusReport + "Is low on toner. ";
      }
      if ((pq->QueueStatus & PrintQueueStatus::UserIntervention) == PrintQueueStatus::UserIntervention)
      {
         statusReport = statusReport + "Needs user intervention. ";
      }

      // Check if queue is even available at this time of day
      // The method below is defined in the complete example.
      ReportAvailabilityAtThisTime(statusReport, pq);
   };
// Check for possible trouble states of a printer using the flags of the QueueStatus property
internal static void SpotTroubleUsingQueueAttributes(ref String statusReport, PrintQueue pq)
{
    if ((pq.QueueStatus & PrintQueueStatus.PaperProblem) == PrintQueueStatus.PaperProblem)
    {
        statusReport = statusReport + "Has a paper problem. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.NoToner) == PrintQueueStatus.NoToner)
    {
        statusReport = statusReport + "Is out of toner. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.DoorOpen) == PrintQueueStatus.DoorOpen)
    {
        statusReport = statusReport + "Has an open door. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.Error) == PrintQueueStatus.Error)
    {
        statusReport = statusReport + "Is in an error state. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.NotAvailable) == PrintQueueStatus.NotAvailable)
    {
        statusReport = statusReport + "Is not available. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.Offline) == PrintQueueStatus.Offline)
    {
        statusReport = statusReport + "Is off line. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.OutOfMemory) == PrintQueueStatus.OutOfMemory)
    {
        statusReport = statusReport + "Is out of memory. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.PaperOut) == PrintQueueStatus.PaperOut)
    {
        statusReport = statusReport + "Is out of paper. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.OutputBinFull) == PrintQueueStatus.OutputBinFull)
    {
        statusReport = statusReport + "Has a full output bin. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.PaperJam) == PrintQueueStatus.PaperJam)
    {
        statusReport = statusReport + "Has a paper jam. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.Paused) == PrintQueueStatus.Paused)
    {
        statusReport = statusReport + "Is paused. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.TonerLow) == PrintQueueStatus.TonerLow)
    {
        statusReport = statusReport + "Is low on toner. ";
    }
    if ((pq.QueueStatus & PrintQueueStatus.UserIntervention) == PrintQueueStatus.UserIntervention)
    {
        statusReport = statusReport + "Needs user intervention. ";
    }

    // Check if queue is even available at this time of day
    // The method below is defined in the complete example.
    ReportAvailabilityAtThisTime(ref statusReport, pq);
}
' Check for possible trouble states of a printer using the flags of the QueueStatus property
Friend Shared Sub SpotTroubleUsingQueueAttributes(ByRef statusReport As String, ByVal pq As PrintQueue)
    If (pq.QueueStatus And PrintQueueStatus.PaperProblem) = PrintQueueStatus.PaperProblem Then
        statusReport = statusReport & "Has a paper problem. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.NoToner) = PrintQueueStatus.NoToner Then
        statusReport = statusReport & "Is out of toner. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.DoorOpen) = PrintQueueStatus.DoorOpen Then
        statusReport = statusReport & "Has an open door. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.Error) = PrintQueueStatus.Error Then
        statusReport = statusReport & "Is in an error state. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.NotAvailable) = PrintQueueStatus.NotAvailable Then
        statusReport = statusReport & "Is not available. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.Offline) = PrintQueueStatus.Offline Then
        statusReport = statusReport & "Is off line. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.OutOfMemory) = PrintQueueStatus.OutOfMemory Then
        statusReport = statusReport & "Is out of memory. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.PaperOut) = PrintQueueStatus.PaperOut Then
        statusReport = statusReport & "Is out of paper. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.OutputBinFull) = PrintQueueStatus.OutputBinFull Then
        statusReport = statusReport & "Has a full output bin. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.PaperJam) = PrintQueueStatus.PaperJam Then
        statusReport = statusReport & "Has a paper jam. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.Paused) = PrintQueueStatus.Paused Then
        statusReport = statusReport & "Is paused. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.TonerLow) = PrintQueueStatus.TonerLow Then
        statusReport = statusReport & "Is low on toner. "
    End If
    If (pq.QueueStatus And PrintQueueStatus.UserIntervention) = PrintQueueStatus.UserIntervention Then
        statusReport = statusReport & "Needs user intervention. "
    End If

    ' Check if queue is even available at this time of day
    ' The method below is defined in the complete example.
    ReportAvailabilityAtThisTime(statusReport, pq)
End Sub

Para verificar o status da impressora usando cada propriedade, basta ler cada propriedade e adicionar uma anotação ao relatório final que será apresentada ao usuário se a propriedade for true. (O método ReportAvailabilityAtThisTime que é chamado no final do código é discutido abaixo.)

internal: 
   // Check for possible trouble states of a printer using its properties
   static void SpotTroubleUsingProperties (System::String^% statusReport, System::Printing::PrintQueue^ pq) 
   {
      if (pq->HasPaperProblem)
      {
         statusReport = statusReport + "Has a paper problem. ";
      }
      if (!(pq->HasToner))
      {
         statusReport = statusReport + "Is out of toner. ";
      }
      if (pq->IsDoorOpened)
      {
         statusReport = statusReport + "Has an open door. ";
      }
      if (pq->IsInError)
      {
         statusReport = statusReport + "Is in an error state. ";
      }
      if (pq->IsNotAvailable)
      {
         statusReport = statusReport + "Is not available. ";
      }
      if (pq->IsOffline)
      {
         statusReport = statusReport + "Is off line. ";
      }
      if (pq->IsOutOfMemory)
      {
         statusReport = statusReport + "Is out of memory. ";
      }
      if (pq->IsOutOfPaper)
      {
         statusReport = statusReport + "Is out of paper. ";
      }
      if (pq->IsOutputBinFull)
      {
         statusReport = statusReport + "Has a full output bin. ";
      }
      if (pq->IsPaperJammed)
      {
         statusReport = statusReport + "Has a paper jam. ";
      }
      if (pq->IsPaused)
      {
         statusReport = statusReport + "Is paused. ";
      }
      if (pq->IsTonerLow)
      {
         statusReport = statusReport + "Is low on toner. ";
      }
      if (pq->NeedUserIntervention)
      {
         statusReport = statusReport + "Needs user intervention. ";
      }

      // Check if queue is even available at this time of day
      // The following method is defined in the complete example.
      ReportAvailabilityAtThisTime(statusReport, pq);
   };
// Check for possible trouble states of a printer using its properties
internal static void SpotTroubleUsingProperties(ref String statusReport, PrintQueue pq)
{
    if (pq.HasPaperProblem)
    {
        statusReport = statusReport + "Has a paper problem. ";
    }
    if (!(pq.HasToner))
    {
        statusReport = statusReport + "Is out of toner. ";
    }
    if (pq.IsDoorOpened)
    {
        statusReport = statusReport + "Has an open door. ";
    }
    if (pq.IsInError)
    {
        statusReport = statusReport + "Is in an error state. ";
    }
    if (pq.IsNotAvailable)
    {
        statusReport = statusReport + "Is not available. ";
    }
    if (pq.IsOffline)
    {
        statusReport = statusReport + "Is off line. ";
    }
    if (pq.IsOutOfMemory)
    {
        statusReport = statusReport + "Is out of memory. ";
    }
    if (pq.IsOutOfPaper)
    {
        statusReport = statusReport + "Is out of paper. ";
    }
    if (pq.IsOutputBinFull)
    {
        statusReport = statusReport + "Has a full output bin. ";
    }
    if (pq.IsPaperJammed)
    {
        statusReport = statusReport + "Has a paper jam. ";
    }
    if (pq.IsPaused)
    {
        statusReport = statusReport + "Is paused. ";
    }
    if (pq.IsTonerLow)
    {
        statusReport = statusReport + "Is low on toner. ";
    }
    if (pq.NeedUserIntervention)
    {
        statusReport = statusReport + "Needs user intervention. ";
    }

    // Check if queue is even available at this time of day
    // The following method is defined in the complete example.
    ReportAvailabilityAtThisTime(ref statusReport, pq);
}//end SpotTroubleUsingProperties
' Check for possible trouble states of a printer using its properties
Friend Shared Sub SpotTroubleUsingProperties(ByRef statusReport As String, ByVal pq As PrintQueue)
    If pq.HasPaperProblem Then
        statusReport = statusReport & "Has a paper problem. "
    End If
    If Not(pq.HasToner) Then
        statusReport = statusReport & "Is out of toner. "
    End If
    If pq.IsDoorOpened Then
        statusReport = statusReport & "Has an open door. "
    End If
    If pq.IsInError Then
        statusReport = statusReport & "Is in an error state. "
    End If
    If pq.IsNotAvailable Then
        statusReport = statusReport & "Is not available. "
    End If
    If pq.IsOffline Then
        statusReport = statusReport & "Is off line. "
    End If
    If pq.IsOutOfMemory Then
        statusReport = statusReport & "Is out of memory. "
    End If
    If pq.IsOutOfPaper Then
        statusReport = statusReport & "Is out of paper. "
    End If
    If pq.IsOutputBinFull Then
        statusReport = statusReport & "Has a full output bin. "
    End If
    If pq.IsPaperJammed Then
        statusReport = statusReport & "Has a paper jam. "
    End If
    If pq.IsPaused Then
        statusReport = statusReport & "Is paused. "
    End If
    If pq.IsTonerLow Then
        statusReport = statusReport & "Is low on toner. "
    End If
    If pq.NeedUserIntervention Then
        statusReport = statusReport & "Needs user intervention. "
    End If

    ' Check if queue is even available at this time of day
    ' The following method is defined in the complete example.
    ReportAvailabilityAtThisTime(statusReport, pq)

End Sub

O método ReportAvailabilityAtThisTime foi criado caso você precise determinar se a fila está disponível na hora atual do dia.

O método não fará nada se as propriedades StartTimeOfDay e UntilTimeOfDay forem iguais; porque, nesse caso, a impressora está disponível o tempo todo. Se forem diferentes, o método obtém a hora atual que, em seguida, deve ser convertida em minutos totais após a meia-noite porque as propriedades StartTimeOfDay e UntilTimeOfDay são Int32que representam minutos após a meia-noite, não DateTime objetos. Por fim, o método verifica se a hora atual está entre o horário de início e o horário de "até".

private: 
   static void ReportAvailabilityAtThisTime (System::String^% statusReport, System::Printing::PrintQueue^ pq) 
   {
      if (pq->StartTimeOfDay != pq->UntilTimeOfDay)
      {
         System::DateTime utcNow = DateTime::UtcNow;
         System::Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;

         // If now is not within the range of available times . . .
         if (!((pq->StartTimeOfDay < utcNowAsMinutesAfterMidnight) && (utcNowAsMinutesAfterMidnight < pq->UntilTimeOfDay)))
         {
            statusReport = statusReport + " Is not available at this time of day. ";
         }
      }
   };
private static void ReportAvailabilityAtThisTime(ref String statusReport, PrintQueue pq)
{
    if (pq.StartTimeOfDay != pq.UntilTimeOfDay) // If the printer is not available 24 hours a day
    {
DateTime utcNow = DateTime.UtcNow;
Int32 utcNowAsMinutesAfterMidnight = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes;

        // If now is not within the range of available times . . .
        if (!((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight)
           &&
           (utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)))
        {
            statusReport = statusReport + " Is not available at this time of day. ";
        }
    }
}
Private Shared Sub ReportAvailabilityAtThisTime(ByRef statusReport As String, ByVal pq As PrintQueue)
    If pq.StartTimeOfDay <> pq.UntilTimeOfDay Then ' If the printer is not available 24 hours a day
Dim utcNow As Date = Date.UtcNow
Dim utcNowAsMinutesAfterMidnight As Int32 = (utcNow.TimeOfDay.Hours * 60) + utcNow.TimeOfDay.Minutes

        ' If now is not within the range of available times . . .
        If Not((pq.StartTimeOfDay < utcNowAsMinutesAfterMidnight) AndAlso (utcNowAsMinutesAfterMidnight < pq.UntilTimeOfDay)) Then
            statusReport = statusReport & " Is not available at this time of day. "
        End If
    End If
End Sub

Consulte também