Como: Sondar Remotamente o Status de Impressoras
A qualquer momento em médias e grandes empresas pode haver várias impressoras que não estão trabalhando devido para uma obstrução de papel ou falta de papel ou alguma outra situação problemática. O conjunto de propriedades da impressora expostas na caixa APIs de Microsoft .NET Framework fornece um meio para executar uma pesquisa rápida dos estados de impressoras.
Exemplo
As principais etapas para criar esse tipo de utilitário são as seguintes.
Obter uma lista de todos os servidores de impressão.
Iterar através dos servidores para consultar suas filas de impressão.
Em cada vez que itrar por um servidor, iterar por todas as filas do servidor e ler cada propriedade que pode indicar que a fila não está funcionando no momento.
O código a seguir é uma série de trechos de código. For the complete sample, see Status de pesquisa do exemplo de impressoras.
Para simplificar, este exemplo assume que há uma lista delimitada por CRLF de servidores de impressão. A variável fileOfPrintServers é um objeto StreamReader para este arquivo. Como cada nome de servidor está em sua própria linha, qualquer chamada de ReadLine obtém o próximo nome do servidor e move cursor do StreamReader para 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.
Observação: |
---|
Se houver muitos servidores, Você pode melhorar o desempenho por usando o PrintServer(String, array<String[], PrintSystemDesiredAccess) construtores inicializar somente as propriedades que você vai precisar. |
O exemplo, em seguida, usa GetPrintQueues para criar uma coleção de todas as filas do servidor e começa a iterar sobre eles. Este loop interno contém uma estrutura de ramificação correspondente a duas maneiras de verificar o status de uma impressora:
Você pode ler os sinalizadores da propriedade QueueStatus quel é do tipo PrintQueueStatus.
Você pode ler cada propriedade relevante, como IsOutOfPaper e IsPaperJammed.
Este exemplo demonstra ambos métodos, o usuário foi previamente solicitado sobre qual método usar e ele respondeu com "y" se ele ou ela quisesse usar os sinalizadores da propriedade QueueStatus. Consulte abaixo para obter os detalhes dos dois métodos.
Finalmente, o resultado é apresentado ao usuário.
// 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
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();
Para verificar o status da impressora usando os sinalizadores da propriedade QueueStatus, verifique cada sinalizador relevante para ver se ela está definida. A maneira padrão para ver se um bit é definido em um conjunto de sinalizadores de bit é realizar uma operação AND lógica com o conjunto de sinalizadores como um operando e o sinalizador próprio como o outro. Desde que o sinalizador próprio tem apenas um bit definido, o resultado da lógica AND é que, no máximo, esse mesmo bit será definido. Para saber se ele é ou não, apenas compare o resultado da lógica AND com o próprio sinalizador. Para mais informações, consulte PrintQueueStatus, & Operador (Referência C#), e FlagsAttribute.
Para cada atributo cujo bit for definido, o código adiciona um aviso para o relatório final que será apresentado ao usuário. (O método ReportAvailabilityAtThisTime que é chamado no final do código é discutido abaixo).
// 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);
}
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);
};
Para verificar o status da impressora usando cada propriedade, você simplesmente lê cada propriedade e adiciona uma observação para o relatório final que será apresentado ao usuário se a propriedade for true. (O método ReportAvailabilityAtThisTime que é chamado no final do código é discutido abaixo).
// 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
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);
};
O método ReportAvailabilityAtThisTime foi criado caso você precise determinar se a fila está disponível no momento atual do dia.
O método não fará nada se o StartTimeOfDay e as propriedades UntilTimeOfDay são iguais; porque nesse caso, a impressora está disponível o tempo todo. Se eles forem diferentes, o método obtém a hora atual, que em seguida tem que ser convertida no total de minutos após a meia noite , pois o StartTimeOfDay UntilTimeOfDay propriedades e Int32 s representando minutes representam minutos após a meia noite, não objetos DateTime. Finalmente, o método faz uma verificação para averiguar se o horário atual está entre o horário de início e final.
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:
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. ";
}
}
};
Consulte também
Conceitos
Documentos em Windows Presentation Foundation