Cómo: Supervisar de forma remota el estado de las impresoras
En un momento dado, en las empresas de tamaño medio y grande puede haber varias impresoras que no funcionen debido a un atasco del papel, que se queden sin papel y otras situaciones problemáticas. El amplio conjunto de propiedades del trabajo de impresión expuesto en las API de Microsoft .NET Framework proporciona un medio para realizar una encuesta rápida del estado de las impresoras.
Ejemplo
Los pasos principales para crear este tipo de utilidad son los siguientes.
Obtener una lista de todos los servidores de impresión.
Recorrer los servidores para consultar sus colas de impresión.
Dentro de cada paso del bucle de servidor, recorra en iteración todas las colas del servidor y lea cada propiedad que podría indicar que la cola no está funcionando actualmente.
El código siguiente es una serie de fragmentos de código. Para simplificar, en este ejemplo se da por hecho que hay una lista delimitada por CRLF de servidores de impresión. La variable fileOfPrintServers
es un objeto StreamReader para este archivo. Dado que cada nombre de servidor está en su propia línea, cualquier llamada de ReadLine obtiene el nombre del servidor siguiente y mueve el cursor de StreamReader al principio de la línea siguiente.
Dentro del bucle exterior, el código crea un objeto PrintServer para el servidor de impresión más reciente y especifica que la aplicación va a tener derechos administrativos en el servidor.
Nota:
Si hay muchos servidores, puede mejorar el rendimiento con los constructores PrintServer(String, String[], PrintSystemDesiredAccess), que solo inicializarán las propiedades que vaya a necesitar.
El ejemplo utiliza GetPrintQueues para crear una colección de todas las colas de servidores y comienza a recorrerlas. Este bucle interno contiene una estructura de bifurcación correspondiente a las dos maneras de comprobar el estado de la impresora:
Puede leer las marcas de la propiedad QueueStatus, que es de tipo PrintQueueStatus.
Puede leer cada propiedad relevante como IsOutOfPaper y IsPaperJammed.
En este ejemplo se muestran ambos métodos, por lo que se le preguntó al usuario anteriormente qué método utilizar y respondió con "y" si quería utilizar los marcadores de la propiedad QueueStatus. A continuación encontrará los detalles de los dos métodos.
Por último, los resultados se presentan al usuario.
// 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 comprobar el estado de la impresora mediante los marcadores de la propiedad QueueStatus, se comprueba cada marcador pertinente para ver si está establecido. El modo estándar para ver si un bit se establece en un conjunto de marcadores de bits es realizar una operación AND lógica con el conjunto de marcadores como uno de los operandos y la propia marca como el otro. Puesto que el propio marcador solo tiene un bit establecido, el resultado del operador lógico AND es que, como máximo, se establezca ese mismo bit. Para averiguar si esto ocurre o no, basta con comparar el resultado del operador lógico AND y el propio marcador. Para obtener más información, consulte PrintQueueStatus, el operador & (referencia C#) y FlagsAttribute.
Para cada atributo cuyo bit esté establecido, el código agrega un aviso al informe final que se presentará al usuario. (Se trata a continuación el método ReportAvailabilityAtThisTime que se llama al final del código).
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 comprobar el estado de la impresora mediante cada propiedad, simplemente lea cada propiedad y agregue una nota al informe final, que se presentará al usuario si la propiedad es true
. (Se trata a continuación el método ReportAvailabilityAtThisTime que se llama al final del código).
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
El método ReportAvailabilityAtThisTime se creó por si necesita determinar si la cola está disponible en el momento actual del día.
Este método no tendrá resultado si las propiedades StartTimeOfDay y UntilTimeOfDay son iguales, ya que en ese caso la impresora estará disponible en todo momento. Si son diferentes, el método obtiene el tiempo actual que luego debe convertirse en el total de minutos después de medianoche, ya que las propiedades StartTimeOfDay y UntilTimeOfDay son Int32 s que representan los minutos después de medianoche, no los objetos DateTime. Por último, el método comprueba si la hora actual se encuentra entre el inicio y las horas "hasta".
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 también
.NET Desktop feedback