【问题标题】:Access Denied trying to purge printqueue in C#访问被拒绝尝试在 C# 中清除 printqueue
【发布时间】:2011-12-01 21:47:04
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 您是否尝试过以管理员身份运行您的流程/视觉工作室?
  • 我将 Visual Studio 的 EXE 设置为始终以管理员身份运行,重新启动 Visual Studio 2010 并再次尝试。仍然收到相同的访问被拒绝错误。
  • 尝试右键单击输出的 .exe 文件 (YourProgramName.exe) 并选择以管理员身份运行。
  • 您的用户帐户没有足够的权限。开始,打印机+设备,右键单击打印机,打印机属性,安全选项卡。在 superuser.com 上询问有关它的更多问题
  • 这个问题解决了吗?我遇到了同样的问题。

标签: c# access-denied printqueue


【解决方案1】:

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

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

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

如果您未在管理员组成员的上下文中运行(或未以提升的权限运行),这仍可能导致权限错误,因此使用 try/catch 块围绕此问题对于生产代码来说是个好主意.

【讨论】:

  • 这非常有帮助。我还尝试使用 GetPrintQueue() 方法进行更改。 +1
  • 对 PrintServer 请求的权限不被通过它检索的 PrintQueue 继承这一事实提供了非常好的见解!
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我尝试使用@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();
          }
       }
    }
    

    【讨论】:

      【解决方案4】:

      //以这个为例让你开始......

       /// <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;
             }
       }
      

      【讨论】:

        【解决方案5】:

        如果你不介意清除本地机器上的所有队列,你可以使用下面的sn -p。它需要管理员权限,但不会抛出异常:

        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();
        

        【讨论】:

          【解决方案6】:

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-10-01
            • 2023-04-04
            • 1970-01-01
            • 1970-01-01
            • 2016-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多