Практическое руководство. Диагностика проблем при выполнении заданий печати
Администраторы сетей часто получают от пользователей жалобы на то, что задания печати не выполняются или выполняются слишком медленно. Широкий набор свойств заданий печати в API платформы Microsoft .NET Framework предоставляют средства для выполнения быструю удаленную диагностику заданий печати.
Пример
Ниже представлены основные этапы создания подобной служебной программы.
Определите, на какое задание печати жалуется пользователь. Части пользователи не могут указать его точно. Они могут не знать имена серверов печати или принтеров. Пользователи могут описывать расположение принтера в терминологии, который использовался в параметрах его Location свойство. В связи с этим будет полезно составить список задач, отправленных пользователем на данный момент. Если их несколько, определить, какое именно задание вызывает проблемы, позволит взаимодействие между пользователем и системным администратором печати. Порядок действий при этом следующий:
Получите список всех серверов печати.
Выполните циклический просмотр всех серверов, чтобы запросить их очереди печати.
Для каждого сервера выполните циклический просмотр всех очередей сервера, чтобы запросить их задания.
Для каждого цикла очереди выполните циклический просмотр ее заданий и соберите идентификационные данные заданий, отправленных подавшим жалобу пользователем.
Обнаружив проблемное задание, изучите соответствующие свойства, чтобы узнать, в чем может быть проблема. Например, определите, находится ли задание в состоянии ошибки и не отключился ли обслуживающий очередь принтер от сети перед печатью задания.
Приведенный ниже код представляет собой последовательность примеров кода. Код в первом примере кода содержит циклический просмотр очередей печати. (Шаг 1c выше.) Переменная myPrintQueues
является PrintQueueCollection объект для текущего сервера печати.
В примере кода начинается с обновления текущего объекта очереди печати с PrintQueue.Refresh. Это гарантирует, что свойства объекта точно отображают состояние физического принтера, который он представляет. Затем приложение получает коллекцию заданий печати в настоящее время в очереди печати с помощью GetPrintJobInfoCollection.
Затем приложение выполняет цикл по PrintSystemJobInfo коллекции и сравнивает Submitter свойство с псевдонимом подавшего жалобу пользователя. Если они совпадают, приложение добавляет идентификационные сведения о задании в предоставляемую строку. (Переменные userName
и jobList
инициализируются в приложении на более раннем этапе.)
foreach (PrintQueue pq in myPrintQueues)
{
pq.Refresh();
PrintJobInfoCollection jobs = pq.GetPrintJobInfoCollection();
foreach (PrintSystemJobInfo job in jobs)
{
// Since the user may not be able to articulate which job is problematic,
// present information about each job the user has submitted.
if (job.Submitter == userName)
{
atLeastOne = true;
jobList = jobList + "\nServer:" + line;
jobList = jobList + "\n\tQueue:" + pq.Name;
jobList = jobList + "\n\tLocation:" + pq.Location;
jobList = jobList + "\n\t\tJob: " + job.JobName + " ID: " + job.JobIdentifier;
}
}// end for each print job
}// end for each print queue
В следующем примере кода выбирается приложение с шага 2. (См. выше.) Проблемное задание обнаружено, и приложение запрашивает данные, которые позволят его идентифицировать. На основе этих данных он создает PrintServer, PrintQueue, и PrintSystemJobInfo объектов.
На этом этапе приложение содержит структуру ветвления, соответствующую двум способам проверки состояния заданий печати:
Вы можете прочесть флаги из JobStatus свойства, которые имеют тип PrintJobStatus.
Можно прочитать каждое соответствующее свойство, например IsBlocked и IsInError.
В этом примере демонстрируются оба метода, поскольку пользователь получил какой метод использовать и ответил «Y», если хотите использовать флаги JobStatus свойство. Ниже представлены подробные сведения об этих двух методах. Наконец, для создания отчетов о возможности печати соответствующего задания в это время суток в приложении используется метод под названием ReportQueueAndJobAvailability. Этот метод обсуждается в разделе Практическое руководство. Определение возможности печати в заданное время суток.
// When the problematic print job has been identified, enter information about it.
Console.Write("\nEnter the print server hosting the job (including leading slashes \\\\): " +
"\n(press Return for the current computer \\\\{0}): ", Environment.MachineName);
String pServer = Console.ReadLine();
if (pServer == "")
{
pServer = "\\\\" +Environment.MachineName;
}
Console.Write("\nEnter the print queue hosting the job: ");
String pQueue = Console.ReadLine();
Console.Write("\nEnter the job ID: ");
Int16 jobID = Convert.ToInt16(Console.ReadLine());
// Create objects to represent the server, queue, and print job.
PrintServer hostingServer = new PrintServer(pServer, PrintSystemDesiredAccess.AdministrateServer);
PrintQueue hostingQueue = new PrintQueue(hostingServer, pQueue, PrintSystemDesiredAccess.AdministratePrinter);
PrintSystemJobInfo theJob = hostingQueue.GetJob(jobID);
if (useAttributesResponse == "Y")
{
TroubleSpotter.SpotTroubleUsingJobAttributes(theJob);
// TroubleSpotter class is defined in the complete example.
}
else
{
TroubleSpotter.SpotTroubleUsingProperties(theJob);
}
TroubleSpotter.ReportQueueAndJobAvailability(theJob);
Чтобы проверить состояние задания печати, используя флаги JobStatus свойство, проверьте каждый соответствующий флаг включен. Обычно определить, задан ли один бит в наборе битовых флагов, позволяет логическая операция И с набором флагов в качестве одной операнды и самим флагом в качестве второй. Поскольку сам флаг имеет только один набор битов, результатом логической операции И может стать максимум установка самого бита. Чтобы определить, установлен ли этот бит, просто сравните результат логической операции И с самим флагом. Дополнительные сведения см. в разделе PrintJobStatus, & оператор (C# ссылку), и FlagsAttribute.
Для каждого атрибута с заданным битом код передает соответствующие данные на экран консоли и иногда предлагает способы реагирования. (Метод HandlePausedJob, который вызывается в случае приостановки задания или очереди, описывается ниже.)
// Check for possible trouble states of a print job using the flags of the JobStatus property
internal static void SpotTroubleUsingJobAttributes(PrintSystemJobInfo theJob)
{
if ((theJob.JobStatus & PrintJobStatus.Blocked) == PrintJobStatus.Blocked)
{
Console.WriteLine("The job is blocked.");
}
if (((theJob.JobStatus & PrintJobStatus.Completed) == PrintJobStatus.Completed)
||
((theJob.JobStatus & PrintJobStatus.Printed) == PrintJobStatus.Printed))
{
Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct printer is being checked.");
}
if (((theJob.JobStatus & PrintJobStatus.Deleted) == PrintJobStatus.Deleted)
||
((theJob.JobStatus & PrintJobStatus.Deleting) == PrintJobStatus.Deleting))
{
Console.WriteLine("The user or someone with administration rights to the queue has deleted the job. It must be resubmitted.");
}
if ((theJob.JobStatus & PrintJobStatus.Error) == PrintJobStatus.Error)
{
Console.WriteLine("The job has errored.");
}
if ((theJob.JobStatus & PrintJobStatus.Offline) == PrintJobStatus.Offline)
{
Console.WriteLine("The printer is offline. Have user put it online with printer front panel.");
}
if ((theJob.JobStatus & PrintJobStatus.PaperOut) == PrintJobStatus.PaperOut)
{
Console.WriteLine("The printer is out of paper of the size required by the job. Have user add paper.");
}
if (((theJob.JobStatus & PrintJobStatus.Paused) == PrintJobStatus.Paused)
||
((theJob.HostingPrintQueue.QueueStatus & PrintQueueStatus.Paused) == PrintQueueStatus.Paused))
{
HandlePausedJob(theJob);
//HandlePausedJob is defined in the complete example.
}
if ((theJob.JobStatus & PrintJobStatus.Printing) == PrintJobStatus.Printing)
{
Console.WriteLine("The job is printing now.");
}
if ((theJob.JobStatus & PrintJobStatus.Spooling) == PrintJobStatus.Spooling)
{
Console.WriteLine("The job is spooling now.");
}
if ((theJob.JobStatus & PrintJobStatus.UserIntervention) == PrintJobStatus.UserIntervention)
{
Console.WriteLine("The printer needs human intervention.");
}
}//end SpotTroubleUsingJobAttributes
Чтобы проверить состояние задания печати с помощью отдельных свойств, просто прочтите каждое свойство и, если свойство имеет значение true
, передайте данные на экран консоли и по возможности предложите способ реагирования. (Метод HandlePausedJob, который вызывается в случае приостановки задания или очереди, описывается ниже.)
// Check for possible trouble states of a print job using its properties
internal static void SpotTroubleUsingProperties(PrintSystemJobInfo theJob)
{
if (theJob.IsBlocked)
{
Console.WriteLine("The job is blocked.");
}
if (theJob.IsCompleted || theJob.IsPrinted)
{
Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct printer is being checked.");
}
if (theJob.IsDeleted || theJob.IsDeleting)
{
Console.WriteLine("The user or someone with administration rights to the queue has deleted the job. It must be resubmitted.");
}
if (theJob.IsInError)
{
Console.WriteLine("The job has errored.");
}
if (theJob.IsOffline)
{
Console.WriteLine("The printer is offline. Have user put it online with printer front panel.");
}
if (theJob.IsPaperOut)
{
Console.WriteLine("The printer is out of paper of the size required by the job. Have user add paper.");
}
if (theJob.IsPaused || theJob.HostingPrintQueue.IsPaused)
{
HandlePausedJob(theJob);
//HandlePausedJob is defined in the complete example.
}
if (theJob.IsPrinting)
{
Console.WriteLine("The job is printing now.");
}
if (theJob.IsSpooling)
{
Console.WriteLine("The job is spooling now.");
}
if (theJob.IsUserInterventionRequired)
{
Console.WriteLine("The printer needs human intervention.");
}
}//end SpotTroubleUsingProperties
Метод HandlePausedJob позволяет пользователю приложения удаленно возобновлять приостановленные задания. Поскольку приостановка очереди печати может быть связана именно с этим, метод начинается с запроса решения пользователя о его возобновлении. Если вы ответили «Y», а затем PrintQueue.Resume вызывается метод.
Затем пользователю предлагается решить, следует ли возобновить само задание печати (на случай, если оно было приостановлено независимо от очереди печати). (Сравните PrintQueue.IsPaused и PrintSystemJobInfo.IsPaused.) Если вы ответили «Y», затем PrintSystemJobInfo.Resume вызываемой; в противном случае Cancel вызывается.
internal static void HandlePausedJob(PrintSystemJobInfo theJob)
{
// If there's no good reason for the queue to be paused, resume it and
// give user choice to resume or cancel the job.
Console.WriteLine("The user or someone with administrative rights to the queue" +
"\nhas paused the job or queue." +
"\nResume the queue? (Has no effect if queue is not paused.)" +
"\nEnter \"Y\" to resume, otherwise press return: ");
String resume = Console.ReadLine();
if (resume == "Y")
{
theJob.HostingPrintQueue.Resume();
// It is possible the job is also paused. Find out how the user wants to handle that.
Console.WriteLine("Does user want to resume print job or cancel it?" +
"\nEnter \"Y\" to resume (any other key cancels the print job): ");
String userDecision = Console.ReadLine();
if (userDecision == "Y")
{
theJob.Resume();
}
else
{
theJob.Cancel();
}
}//end if the queue should be resumed
}//end HandlePausedJob