Поделиться через


Практическое руководство. Диагностика проблем при выполнении заданий печати

Часто администраторы сети получают жалобы от пользователей по поводу заданий печати, которые не выполняются или выполняются медленно. В интерфейсе APIs Microsoft .NET Framework представлен широкий набор свойств заданий печати, обеспечивающих быструю удаленную диагностику заданий печати.

Пример

Ниже приведены основные этапы по созданию служебной программы такого рода.

  1. Идентификация задания печати, на которое жалуется пользователь. Часто пользователи не могут сделать это точно. Они могут не знать имена серверов печати или принтеров. Пользователи могут описывать расположение принтера в терминологии отличной от той, которая была использована при установке свойства Location. В связи с этим рекомендуется создавать список текущих заданий, принятых от пользователей. При наличии нескольких заданий выявление проблемного задания может осуществляться во взаимодействии пользователя и администратора системы печати. Ниже приведены соответствующие промежуточные этапы.

    1. Получите список всех серверов печати.

    2. Выполните цикл опроса серверов об их очередях печати.

    3. На каждом шаге цикла выполните цикл опроса заданий во всех очередях сервера.

    4. На каждом шаге цикла опроса очередей выполните цикл опроса всех заданий и соберите идентифицирующие сведения о заданиях, отправленных жалующимся пользователем.

  2. При выявлении проблемного задания печати просмотрите соответствующие свойства для определения источника проблемы. Например, задание может находиться в состоянии ошибки, или перед печатью задания выключен принтер, обслуживающий очередь.

В приведенном ниже коде представлен ряд примеров. В первом примере кода представлен цикл опроса очередей печати. (Шаг «1в» выше.) Переменная myPrintQueues представляет собой объект класса PrintQueueCollection для текущего сервера печати.

Пример кода начинается с обновления текущего объекта очереди печати с помощью метода PrintQueue.Refresh. Это гарантирует точное представление состояния соответствующего физического принтера с помощью свойств объекта. Затем в приложении извлекается текущая коллекцию заданий печати в очереди с помощью метода GetPrintJobInfoCollection.

После этого в приложении просматривается коллекция PrintSystemJobInfo, каждое свойство Submitter в которой сравнивается с псевдонимом жалующегося пользователя. Если они совпадают, идентифицирующие сведения о задании добавляются к соответствующей строке. (Переменные userName и jobList инициализируются в приложении ранее.)

                For Each pq As PrintQueue In myPrintQueues
                    pq.Refresh()
                    Dim jobs As PrintJobInfoCollection = pq.GetPrintJobInfoCollection()
                    For Each job As PrintSystemJobInfo 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 Then
                            atLeastOne = True
                            jobList = jobList & vbLf & "Server:" & line
                            jobList = jobList & vbLf & vbTab & "Queue:" & pq.Name
                            jobList = jobList & vbLf & vbTab & "Location:" & pq.Location
                            jobList = jobList & vbLf & vbTab & vbTab & "Job: " & job.JobName & " ID: " & job.JobIdentifier
                        End If
                    Next job ' end for each print job

                Next pq ' end for each print queue
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
for each (PrintQueue^ pq in myPrintQueues)
{
   pq->Refresh();
   PrintJobInfoCollection^ jobs = pq->GetPrintJobInfoCollection();
   for each (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;
      }
   }
}

В следующем примере выбирается приложение на шаге 2. (См. выше.) После определения проблемного задания в приложении запрашиваются сведения, которые будут идентифицировать это задание. На основании этих сведений создаются объекты PrintServer, PrintQueue и PrintSystemJobInfo.

На этом этапе в приложении содержится структура ветвления, соответствующая двум способам проверки состояния задачи печати:

  • чтение флагов свойства JobStatus, имеющего тип PrintJobStatus;

  • чтение каждого соответствующего свойства, например IsBlocked и IsInError.

В этом примере демонстрируются оба метода. Пользователь имеет возможность заранее выбрать используемый метод (чтобы использовать флаги свойства JobStatus, следует выбрать ответ «Y»). Ниже приведены сведения об этих двух методах. В завершение, в приложении используется метод ReportQueueAndJobAvailability для определения возможности печати задания в это время дня. Описание этого метода см. в разделе Практическое руководство. Определение возможности печати в заданное время суток.

                ' When the problematic print job has been identified, enter information about it.
                Console.Write(vbLf & "Enter the print server hosting the job (including leading slashes \\): " & vbLf & "(press Return for the current computer \\{0}): ", Environment.MachineName)
                Dim pServer As String = Console.ReadLine()
                If pServer = "" Then
                    pServer = "\\" & Environment.MachineName
                End If
                Console.Write(vbLf & "Enter the print queue hosting the job: ")
                Dim pQueue As String = Console.ReadLine()
                Console.Write(vbLf & "Enter the job ID: ")
                Dim jobID As Int16 = Convert.ToInt16(Console.ReadLine())

                ' Create objects to represent the server, queue, and print job.
                Dim hostingServer As New PrintServer(pServer, PrintSystemDesiredAccess.AdministrateServer)
                Dim hostingQueue As New PrintQueue(hostingServer, pQueue, PrintSystemDesiredAccess.AdministratePrinter)
                Dim theJob As PrintSystemJobInfo = hostingQueue.GetJob(jobID)

                If useAttributesResponse = "Y" Then
                    TroubleSpotter.SpotTroubleUsingJobAttributes(theJob)
                    ' TroubleSpotter class is defined in the complete example.
                Else
                    TroubleSpotter.SpotTroubleUsingProperties(theJob)
                End If

                TroubleSpotter.ReportQueueAndJobAvailability(theJob)
// 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);
// 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 = gcnew PrintServer(pServer, PrintSystemDesiredAccess::AdministrateServer);
PrintQueue^ hostingQueue = gcnew 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, следует выполнить проверку состояния всех соответствующих флагов. Стандартным способом просмотра, установлен ли один бит в наборе битовых флагов, является применение логической операции AND с набором флагов в качестве одного операнда и самого флага — в качестве другого. Так как сам флаг имеет только одно битовое значение, результатом применения логического оператора AND является то, что в большинстве случаев устанавливается тот же самый бит. Чтобы узнать, справедливо ли это, просто сравните результат применения логического оператора AND и значение самого флага. Дополнительные сведения см. в разделах PrintJobStatus, Оператор & (Справочник по C#) и FlagsAttribute.

Для каждого атрибута, для которого установлен этот бит, в окне консоли выводится соответствующее уведомление, а в некоторых случаях также предлагаются способы реагирования. (Метод HandlePausedJob, который вызывается в случае приостановки задания или очереди, описывается ниже.)

        ' Check for possible trouble states of a print job using the flags of the JobStatus property
        Friend Shared Sub SpotTroubleUsingJobAttributes(ByVal theJob As PrintSystemJobInfo)
            If (theJob.JobStatus And PrintJobStatus.Blocked) = PrintJobStatus.Blocked Then
                Console.WriteLine("The job is blocked.")
            End If
            If ((theJob.JobStatus And PrintJobStatus.Completed) = PrintJobStatus.Completed) OrElse ((theJob.JobStatus And PrintJobStatus.Printed) = PrintJobStatus.Printed) Then
                Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct printer is being checked.")
            End If
            If ((theJob.JobStatus And PrintJobStatus.Deleted) = PrintJobStatus.Deleted) OrElse ((theJob.JobStatus And PrintJobStatus.Deleting) = PrintJobStatus.Deleting) Then
                Console.WriteLine("The user or someone with administration rights to the queue has deleted the job. It must be resubmitted.")
            End If
            If (theJob.JobStatus And PrintJobStatus.Error) = PrintJobStatus.Error Then
                Console.WriteLine("The job has errored.")
            End If
            If (theJob.JobStatus And PrintJobStatus.Offline) = PrintJobStatus.Offline Then
                Console.WriteLine("The printer is offline. Have user put it online with printer front panel.")
            End If
            If (theJob.JobStatus And PrintJobStatus.PaperOut) = PrintJobStatus.PaperOut Then
                Console.WriteLine("The printer is out of paper of the size required by the job. Have user add paper.")
            End If

            If ((theJob.JobStatus And PrintJobStatus.Paused) = PrintJobStatus.Paused) OrElse ((theJob.HostingPrintQueue.QueueStatus And PrintQueueStatus.Paused) = PrintQueueStatus.Paused) Then
                HandlePausedJob(theJob)
                'HandlePausedJob is defined in the complete example.
            End If

            If (theJob.JobStatus And PrintJobStatus.Printing) = PrintJobStatus.Printing Then
                Console.WriteLine("The job is printing now.")
            End If
            If (theJob.JobStatus And PrintJobStatus.Spooling) = PrintJobStatus.Spooling Then
                Console.WriteLine("The job is spooling now.")
            End If
            If (theJob.JobStatus And PrintJobStatus.UserIntervention) = PrintJobStatus.UserIntervention Then
                Console.WriteLine("The printer needs human intervention.")
            End If

        End Sub 'end SpotTroubleUsingJobAttributes
// 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
// Check for possible trouble states of a print job using the flags of the JobStatus property
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.");
   }
};

Чтобы проверить состояние задания печати с помощью отдельных свойств, следует считать соответствующие свойства и вывести уведомления и возможные способы реагирования для свойств со значениями true в окне консоли. (Метод HandlePausedJob, который вызывается в случае приостановки задания или очереди, описывается ниже.)

        ' Check for possible trouble states of a print job using its properties
        Friend Shared Sub SpotTroubleUsingProperties(ByVal theJob As PrintSystemJobInfo)
            If theJob.IsBlocked Then
                Console.WriteLine("The job is blocked.")
            End If
            If theJob.IsCompleted OrElse theJob.IsPrinted Then
                Console.WriteLine("The job has finished. Have user recheck all output bins and be sure the correct printer is being checked.")
            End If
            If theJob.IsDeleted OrElse theJob.IsDeleting Then
                Console.WriteLine("The user or someone with administration rights to the queue has deleted the job. It must be resubmitted.")
            End If
            If theJob.IsInError Then
                Console.WriteLine("The job has errored.")
            End If
            If theJob.IsOffline Then
                Console.WriteLine("The printer is offline. Have user put it online with printer front panel.")
            End If
            If theJob.IsPaperOut Then
                Console.WriteLine("The printer is out of paper of the size required by the job. Have user add paper.")
            End If

            If theJob.IsPaused OrElse theJob.HostingPrintQueue.IsPaused Then
                HandlePausedJob(theJob)
                'HandlePausedJob is defined in the complete example.
            End If

            If theJob.IsPrinting Then
                Console.WriteLine("The job is printing now.")
            End If
            If theJob.IsSpooling Then
                Console.WriteLine("The job is spooling now.")
            End If
            If theJob.IsUserInterventionRequired Then
                Console.WriteLine("The printer needs human intervention.")
            End If

        End Sub 'end SpotTroubleUsingProperties
// 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
// Check for possible trouble states of a print job using its properties
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.");
   }
};

Метод HandlePausedJob позволяет пользователю приложения удаленно возобновить приостановленные задания. Поскольку приостановка очереди печати может быть вызвана необходимостью, при выполнении метода сначала отображается запрос на продолжение печати. При выборе варианта «Y» вызывается метод PrintQueue.Resume.

После этого отображается запрос на автоматическое возобновление задания, приостановленного независимо от очереди печати. (Сравните значения свойств PrintQueue.IsPaused и PrintSystemJobInfo.IsPaused.) При выборе варианта «Y» вызывается метод PrintSystemJobInfo.Resume. В противном случае вызывается метод Cancel.

        Friend Shared Sub HandlePausedJob(ByVal theJob As PrintSystemJobInfo)
            ' 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" & vbLf & "has paused the job or queue." & vbLf & "Resume the queue? (Has no effect if queue is not paused.)" & vbLf & "Enter ""Y"" to resume, otherwise press return: ")
            Dim [resume] As String = Console.ReadLine()
            If [resume] = "Y" Then
                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?" & vbLf & "Enter ""Y"" to resume (any other key cancels the print job): ")
                Dim userDecision As String = Console.ReadLine()
                If userDecision = "Y" Then
                    theJob.Resume()
                Else
                    theJob.Cancel()
                End If
            End If 'end if the queue should be resumed

        End Sub 'end HandlePausedJob
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
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();
      }
   }
};

См. также

Ссылки

PrintJobStatus

PrintSystemJobInfo

Оператор & (Справочник по C#)

FlagsAttribute

PrintQueue

Основные понятия

Документы в WPF

Общие сведения о печати