Отказано в доступе при попытке удалить printqueue в C # - PullRequest
7 голосов
/ 02 декабря 2011

Я пытаюсь создать метод в C #, который очищает все элементы в очереди печати. Ниже мой код:

LocalPrintServer localPrintServer = new LocalPrintServer(PrintSystemDesiredAccess.AdministratePrinter); 
PrintQueue printQueue = localPrintServer.GetPrintQueue(printerName);

if (printQueue.NumberOfJobs > 0)
{
    printQueue.Purge();
}

Когда этот код выполняется, в конструкторе localPrintServer приложение выдает эту ошибку: «Произошла исключительная ситуация при создании объекта PrintServer. Ошибка Win32: доступ запрещен.»

Этот конструктор имеет несколько перегрузок (включая отправку без параметров). Пытаясь что-нибудь из этого, я пропускаю эту строку, но когда я получаю вызов printQueue.Purge (), я получаю то же сообщение об отказе в доступе, как указано выше.

Ищу предложения о том, как / что я могу сделать, чтобы обойти это. Я могу вручную удалить задания на печать с моего компьютера. Я не уверен, что приложение работает с тем же доступом, что и у меня, и как это проверить.

Ответы [ 6 ]

13 голосов
/ 24 июня 2013

Эта проблема вызвана тем, что метод GetPrintQueue является слегка злым, поскольку он не позволяет вам перейти на желаемый уровень доступа.С вашим кодом, как он есть, вы подключаетесь к серверу печати с правами AdministratePrinter (что бессмысленно) и подключаетесь к очереди печати с правами пользователя по умолчанию.Таким образом, операция завершится ошибкой, даже если Все имеют права администратора в очереди печати. ​​

Чтобы исправить это, используйте конструктор для PrintQueue вместо того, чтобы указать правильный уровень доступа:

using (PrintServer ps = new PrintServer()) {
    using (PrintQueue pq = new PrintQueue(ps, printerName,
          PrintSystemDesiredAccess.AdministratePrinter)) {
        pq.Purge();
    }
}

Это может по-прежнему вызывать ошибки прав доступа, если вы не работаете в контексте члена группы администраторов (или не работаете с повышенными разрешениями), поэтому окружение этого блоком try / catch являетсяхорошая идея для производственного кода.

2 голосов
/ 04 февраля 2016

Вы используете свой сайт как 4.0?Я столкнулся с проблемами, когда мы обновили наш сайт с 3.5 до 4.0 Framework.Функциональность «Очистка печати» перестала работать в 4.0 Framework.В конечном итоге я закончил тем, что создал веб-сервис, который использовал платформу 3.5 и веб-сайт 4.0 сообщал о принтере, который он хотел очистить, для веб-службы 3.5.Я наткнулся на, когда искал ответ. Я решил опубликовать это, если это поможет кому-то, кто сталкивается с такой же ситуацией)

0 голосов
/ 23 января 2019

Я пытался использовать решение @mdb, но оно не работало (доступ запрещен с помощью Framework .NET 4.6.1). В итоге я использовал следующее решение:

void CleanPrinterQueue(string printerName)         
{   
   using (var ps = new PrintServer())
   {
      using (var pq = new PrintQueue(ps, printerName, PrintSystemDesiredAccess.UsePrinter))
      {
         foreach (var job in pq.GetPrintJobInfoCollection())
            job.Cancel();
      }
   }
}
0 голосов
/ 15 июня 2016

Недавно я столкнулся с той же проблемой после обновления .net framework с 4.0 до 4.6.1.Как ни странно, мое приложение .net работало на .net 3.5, но это изменение каким-то образом повлияло на него.

В любом случае, я запустил свое приложение с помощью планировщика задач, и исправление заключается в щелчке правой кнопкой мыши нав общем случае поставьте галочку в поле «Запускать с наивысшими привилегиями».

Я думаю, что если вы запускаете его на консоли, вам нужно «Запуск от имени администратора» при открытии окна cmd.

0 голосов
/ 19 марта 2012

Если вы не возражаете очистить все очереди на локальном компьютере, вы можете использовать следующий фрагмент. Это требует прав администратора, но не вызывает исключений:

System.ServiceProcess.ServiceController controller = new   System.ServiceProcess.ServiceController("Spooler");
                controller.Stop();
                System.IO.DirectoryInfo info = new System.IO.DirectoryInfo(@"C:\Windows\System32\spool\PRINTERS");

                var files = info.GetFiles();

                foreach (var file in files)
                {
                    file.Delete();
                }
                controller.Start();
0 голосов
/ 02 декабря 2011

// используйте это как пример, чтобы начать ...

 /// <summary>
 /// Cancel the print job. This functions accepts the job number.
 /// An exception will be thrown if access denied.
 /// </summary>
 /// <param name="printJobID">int: Job number to cancel printing for.</param>
 /// <returns>bool: true if cancel successfull, else false.</returns>
 public bool CancelPrintJob(int printJobID)
 {
      // Variable declarations.
      bool isActionPerformed = false;
      string searchQuery;
      String jobName;
      char[] splitArr;
      int prntJobID;
      ManagementObjectSearcher searchPrintJobs;
      ManagementObjectCollection prntJobCollection;
      try
      {
            // Query to get all the queued printer jobs.
           searchQuery = "SELECT * FROM Win32_PrintJob";
           // Create an object using the above query.
           searchPrintJobs = new ManagementObjectSearcher(searchQuery);
          // Fire the query to get the collection of the printer jobs.
           prntJobCollection = searchPrintJobs.Get();

           // Look for the job you want to delete/cancel.
           foreach (ManagementObject prntJob in prntJobCollection)
           {
                 jobName = prntJob.Properties["Name"].Value.ToString();
                 // Job name would be of the format [Printer name], [Job ID]
                 splitArr = new char[1];
                 splitArr[0] = Convert.ToChar(",");
                 // Get the job ID.
                 prntJobID = Convert.ToInt32(jobName.Split(splitArr)[1]);
                 // If the Job Id equals the input job Id, then cancel the job.
                 if (prntJobID == printJobID)
                 {
                       // Performs a action similar to the cancel
                       // operation of windows print console
                       prntJob.Delete();
                       isActionPerformed = true;
                       break;
                  }
           }
           return isActionPerformed;
      }
      catch (Exception sysException)
      {
           // Log the exception.
           return false;
       }
 }
...