访问被拒绝尝试在C#中清除printqueue

Kri*_*ris 7 c# access-denied printqueue

我正在尝试在C#中创建一个清空打印队列中所有项目的方法.以下是我的代码:

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

if (printQueue.NumberOfJobs > 0)
{
    printQueue.Purge();
}
Run Code Online (Sandbox Code Playgroud)

当此代码运行时,在localPrintServer构造函数上,应用程序抛出此错误:"创建PrintServer对象时发生异常.Win32错误:访问被拒绝."

该构造函数有一些重载(包括不发送参数).尝试其中任何一个,我越过那一行,但是当我进入printQueue.Purge()调用时,我得到了与上面列出的相同的访问被拒绝消息.

寻找有关如何/我可以做些什么的建议来解决这个问题.我可以从我的电脑手动删除打印作业.我不确定应用程序是否以相同的访问权限运行,也不确定如何检查.

mdb*_*mdb 14

此问题是由于该GetPrintQueue方法稍微有点恶意造成的,因为它不允许您传递所需的访问级别.使用您的代码,您将连接到具有权限(没有意义)的打印服务器AdministratePrinter,并使用默认用户权限连接到打印队列.因此,即使Everyone对打印队列具有管理员权限,操作也会失败.

要解决此问题,请使用构造函数PrintQueue来指定正确的访问级别:

using (PrintServer ps = new PrintServer()) {
    using (PrintQueue pq = new PrintQueue(ps, printerName,
          PrintSystemDesiredAccess.AdministratePrinter)) {
        pq.Purge();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您没有在Administrators组成员的上下文中运行(或者没有使用提升的权限运行),这可能仍会导致权限错误,因此使用try/catch块进行此操作对于生产代码来说是一个好主意.


Met*_*Man 0

//以此作为示例来帮助您开始...

 /// <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;
       }
 }
Run Code Online (Sandbox Code Playgroud)