如何:远程调查打印机的状态

在大中型公司,在任何给定时间里,都可能发生由于卡纸、纸张用完或某些其他有问题而导致多台打印机无法工作的情况。 Microsoft .NET Framework 的 API 中公开的一组丰富的打印机属性提供一种方法,用于快速调查打印机状态。

示例

以下是创建此类实用程序的主要步骤。

  1. 获取所有打印服务器的列表。

  2. 循环访问服务器以查询其打印队列。

  3. 在每一轮服务器循环访问过程中,循环访问所有服务器的队列并读取每个属性,这些属性可能指示队列当前不在工作。

以下代码是一系列代码段。 为简单起见,本示例假定存在通过 CRLF 分隔的打印服务器列表。 变量 fileOfPrintServers 是该文件的 StreamReader 对象。 由于每个服务器名称是在单独的一行上,因此对 ReadLine 的任何调用将获取下一服务器的名称并将 StreamReader 的光标移动到下一行的开头。

在外部循环中,代码会创建最新打印服务器的 PrintServer 对象,并指定应用程序需具有服务器的管理权限。

注意

如果有很多服务器,可以通过使用 PrintServer(String, String[], PrintSystemDesiredAccess) 构造函数来提高性能,这些构造函数仅初始化需要的属性。

然后,该示例使用 GetPrintQueues 来创建所有服务器队列的集合,并开始对其进行循环访问。 此内部循环包含一个分支结构,该结构对应于检查打印机状态的两种方法:

此示例会演示这两种方法,系统会预先提示用户要使用哪种方法,且如果用户想要使用 QueueStatus 属性的标志,可回复“y”。 请参阅以下有关这两种方法的详细信息。

最后,会向用户显示结果。

// 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()

若要使用 QueueStatus 属性的标志检查打印机状态,请检查每个相关标志以查看是否对其进行了设置。 检查是否在一组位标志中设置了一个位的标准方法是执行一个逻辑 AND 运算,其中将该组标志作为一个操作数,将标志本身作为另一操作数。 由于该标志本身仅设置一个位,因此逻辑 AND 的结果至多为设置了该相同位。 若要查明事实是否如此,只需将逻辑 AND 的结果与标志本身进行比较。 有关详细信息,请参阅 PrintQueueStatus& 运算符(C# 参考)FlagsAttribute

对于已设置了其位的各个特性,代码会将一条通知添加到将向用户显示的最终报告中。 (下面会讨论代码结束时调用的 ReportAvailabilityAtThisTime 方法。)

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

若要使用各个属性检查打印机状态,只需读取各个属性,并将注释添加到最终报告,如果属性为 true,将向用户显示最终报告。 (下面会讨论代码结束时调用的 ReportAvailabilityAtThisTime 方法。)

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

创建了 ReportAvailabilityAtThisTime 方法,以应对需要确定队列在一天的当前时间是否可用的情况。

如果 StartTimeOfDayUntilTimeOfDay 属性相等,该方法将不会执行任何操作;因为在这种情况下,打印机始终可用。 如果它们不同,则该方法将获取当前时间,该时间必须随后转换为午夜过后的总分钟数,因为 StartTimeOfDayUntilTimeOfDay 属性是表示午夜后分钟数的 Int32,而不是 DateTime 对象。 最后,该方法会检查当前时间是否介于开始时间和“截至”时间之间。

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

另请参阅