如何:從遠端調查印表機的狀態
在任何時候,中型和大型公司都可能有多部印表機因為夾紙或紙張用完或一些其他問題狀況而無法運作。 在 Microsoft .NET Framework 的 API 中公開的一組豐富印表機屬性裡提供一種方法來執行印表機狀態的快速問卷調查。
範例
建立這類公用程式的主要步驟如下所示。
取得所有列印伺服器的清單。
對伺服器執行迴圈,以查詢其列印佇列。
在伺服器迴圈的每次操作中,對所有伺服器的佇列執行迴圈,並讀取可能表示佇列目前不在運作中的每個屬性。
下列程式碼是一系列的程式碼片段。 為了簡單起見,本範例假設有列印伺服器的 CRLF 分隔清單。 變數 fileOfPrintServers
是這個檔案的 StreamReader 物件。 由於每部伺服器名稱位於自己的一行上,任何 ReadLine 呼叫都可取得下一部伺服器的名稱,並將 StreamReader 的資料指標移到下一行的開頭。
在外部迴圈內,程式碼會建立最新列印伺服器的 PrintServer 物件,並指定應用程式具有伺服器的系統管理權限。
注意
如果有許多伺服器,您可以使用只初始化所需屬性的 PrintServer(String, String[], PrintSystemDesiredAccess) 建構函式來改善效能。
此範例會接著使用 GetPrintQueues 來建立所有伺服器的佇列集合並開始對其執行迴圈。 此內部迴圈包含一個分支結構,其對應於檢查印表機狀態的兩種方法︰
您可以讀取類型為 PrintQueueStatus 之 QueueStatus 屬性的旗標。
您可以讀取每個相關的屬性,例如 IsOutOfPaper 與 IsPaperJammed。
此範例會示範這兩種方法,所以先前已提示使用者選擇要使用的方法,而且如果他們想要使用 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,Operator (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 方法,以防萬一您需要判斷目前是否可使用佇列。
如果 StartTimeOfDay 和 UntilTimeOfDay 屬性相等,則方法不會執行任何動作;因為在此情況下,印表機隨時都可以使用。 如果兩者不同,則方法會取得目前的時間,然後必須轉換成過去午夜的總分鐘數,因為 StartTimeOfDay 和 UntilTimeOfDay 屬性是 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