10

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

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

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

当此代码在 localPrintServer 构造函数上运行时,应用程序会引发以下错误:“创建 PrintServer 对象时发生异常。Win32 错误:访问被拒绝。”

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

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

4

6 回答 6

19

这个问题是由于该GetPrintQueue方法有点邪恶,因为它不允许您传入所需的访问级别。使用您的代码,您将使用权限连接到打印服务器(这是没有意义的),并使用默认用户权限AdministratePrinter连接到打印队列。因此,即使每个人都拥有打印队列的管理员权限,操作也会失败。

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

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

如果您没有在 Administrators 组成员的上下文中运行(或没有以提升的权限运行),这仍然可能导致权限错误,因此使用 try/catch 块围绕它是生产代码的好主意。

于 2013-06-24T09:34:25.510 回答
2

您是否将网站运行为 4.0?当我们将网站从 3.5 升级到 4.0 框架时,我遇到了问题。打印清除功能在 4.0 框架中停止工作。最终,我最终创建了一个使用 3.5 框架的 Web 服务,并让 4.0 网站将它想要清除的打印机与 3.5 Web 服务通信。

(很抱歉恢复这个线程,这是我在寻找答案时偶然发现的线程之一。我想如果它可以帮助遇到同样情况的人,我会发布这个)

于 2016-02-04T16:36:12.573 回答
1

我尝试使用@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();
      }
   }
}
于 2019-01-23T14:15:41.790 回答
0

If you do not mind clearing all queues on the local machine, you can use the following snippet. It requires admin privileges, but will not throw exceptions:

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();
于 2012-03-19T16:17:57.353 回答
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;
       }
 }
于 2011-12-01T22:10:10.577 回答
0

最近,我将.net框架从4.0升级到4.6.1后也遇到了同样的问题。奇怪的是,我的 .net 应用程序在 .net 3.5 上运行,但不知何故它受到了这种变化的影响。

无论如何,我运行我的应用程序的方式是通过任务调度程序,修复方法是右键单击任务,一般,选中名为“以最高权限运行”的框。

我想如果你在控制台上运行它,你需要在打开 cmd 窗口时“以管理员身份运行”。

于 2016-06-15T06:56:44.913 回答