共用方式為


HOW TO:從遠端調查印表機的狀態

在中型和大型公司中,任何指定的時間內可能都會有多部印表機因卡紙、缺紙或其他某個問題狀況而未作用。 Microsoft .NET Framework 的 APIs 中公開一組豐富的印表機屬性,提供方法來執行印表機狀態的快速調查。

範例

建立這類公用程式的主要步驟如下。

  1. 取得所有列印伺服器的清單。

  2. 在各伺服器之間執行迴圈 (Loop),查詢其列印佇列。

  3. 在伺服器迴圈的每次傳遞中,會在所有伺服器佇列之間執行迴圈,以及讀取可能表示佇列目前未作用的每個屬性。

下列程式碼是程式碼片段的一部分。 為了簡化,這個範例假設具有以 CRLF 分隔的列印伺服器清單。 變數 fileOfPrintServers 是這個檔案的 StreamReader 物件。 因為每個伺服器名稱都有它自己的一行,所以任何 ReadLine 呼叫都會取得下一部伺服器的名稱,並將 StreamReader 的游標移至下一行的開頭。

在外部迴圈中,程式碼會針對最後一部列印伺服器建立 PrintServer 物件,並指定應用程式需要具有伺服器的管理權限。

注意事項注意事項

如果有多部伺服器,則可以使用只會初始化所需要屬性的 PrintServer(String, String[], PrintSystemDesiredAccess) 建構函式,以改善效能。

這個範例接著會使用 GetPrintQueues 來建立所有伺服器佇列的集合,並開始對它們執行迴圈。 這個內部迴圈包含分支結構,而這個分支結構與檢查印表機狀態的兩種方式相對應:

這個範例示範這兩種方法,因此應用程式會先提示使用者選擇使用其中一種方法,並會在使用者想要使用 QueueStatus 屬性的旗標時,回應 "y"。 請看以下對兩種方法的詳細說明。

最後,結果會呈現給使用者。

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

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

若要使用 QueueStatus 屬性的旗標檢查印表機狀態,則請檢查每個相關旗標,查看是否已設定。 若要查看一組位元旗標中是否設定位元,標準的做法是執行邏輯 AND 運算,以這組旗標做為一個運算元,旗標本身則做為另一個運算元。 因為旗標本身只設定一個位元,所以邏輯 AND 運算的結果最多會設定相同的位元。 若要找出是否已設定該位元,則只要比較邏輯 AND 的結果和旗標本身即可。 如需詳細資訊,請參閱 PrintQueueStatus& 運算子 (C# 參考)FlagsAttribute

針對每個已設定位元的屬性,程式碼會在呈現給使用者的最終報告中加入注意事項 (下面會討論在程式碼結尾呼叫的 ReportAvailabilityAtThisTime 方法)。

        ' 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
// 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);
   };

若要使用每個屬性檢查印表機狀態,則只需要讀取每個屬性,並將注意事項加入至屬性為 true 時呈現給使用者的最終報告 (下面會討論在程式碼結尾呼叫的 ReportAvailabilityAtThisTime 方法)。

        ' 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 'end SpotTroubleUsingProperties
// 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);
   };

如果需要判斷佇列目前是否可用,則可以建立 ReportAvailabilityAtThisTime 方法。

如果 StartTimeOfDayUntilTimeOfDay 屬性相等,則這個方法不會有任何作用,原因是在那種情況下,印表機隨時都可以使用。 如果不同,則這個方法會取得目前時間,接著必須將這個時間轉換為午夜之後的分鐘總數,原因是 StartTimeOfDayUntilTimeOfDay 屬性都是表示午夜之後分鐘總數的 Int32,而不是 DateTime 物件。 最後,這個方法會檢查目前時間是否介於開始與「結束」時間之間。

        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
        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. ";
         }
      }
   };

請參閱

參考

StartTimeOfDay

UntilTimeOfDay

DateTime

PrintQueueStatus

& 運算子 (C# 參考)

FlagsAttribute

GetPrintQueues

PrintServer

LocalPrintServer

EnumeratedPrintQueueTypes

PrintQueue

概念

WPF 中的文件

列印概觀