首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >PrintDocument.Print导致Win32Exception操作成功完成

PrintDocument.Print导致Win32Exception操作成功完成
EN

Stack Overflow用户
提问于 2009-09-09 16:46:48
回答 4查看 8.3K关注 0票数 11

我试图在C# .NET 3.5应用程序中打印到网络打印机上,并得到以下异常:

手术成功完成

是什么原因造成的,如何解决呢?

代码语言:javascript
复制
System.ComponentModel.Win32Exception: The operation completed successfully
   at System.Drawing.Printing.PrinterSettings.GetHdevmodeInternal()
   at System.Drawing.Printing.PrinterSettings.GetHdevmode(PageSettings pageSettings)
   at System.Drawing.Printing.PrintController.OnStartPrint(PrintDocument document, PrintEventArgs e)
   at System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument document, PrintEventArgs e)
   at System.Drawing.Printing.PrintController.Print(PrintDocument document)
   at System.Drawing.Printing.PrintDocument.Print()
  • 该帐户具有使用网络打印机打印的权限。权限设置为每个人都要打印。
  • 打印机已被删除并重新创建。
  • 与直接打印到打印机的假脱机设置是双向切换的。
  • 机器上的其他打印机工作正常。
  • 网络上的其他客户端和这台机器上的应用程序可以在这台打印机上打印,而不会发出任何问题。

为了缩小问题范围,我创建了一个简单的控制台应用程序。作为一个正常的用户运行,应用程序打印。当作为服务帐户运行时,它会为服务帐户错误。

针对我的问题的解决方案是卸载导致问题的驱动程序,并安装一个较旧的驱动程序。

EN

回答 4

Stack Overflow用户

发布于 2014-07-11 21:41:42

令人费解的消息是由.NET框架内的pinvoke代码中的一个bug引起的。失败的底层winapi调用是函数。它的pinvoke声明如下所示:

代码语言:javascript
复制
[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DocumentProperties(...);

SetLastError属性是错误的。从MSDN链接中可以看出,该函数通过返回一个负值来指示失败。并且没有文档化来设置GetLastError()返回的错误代码。

这个错误的后果是,框架将调用Marshal.GetLastWin32Error()来获取错误代码,并将得到一个随机值,因为DocumentProperties()没有设置它。0的值并不是不可能的,它会生成“操作成功完成”异常消息。

因此,您需要忽略异常消息,这当然是非常没有帮助的。不幸的是,与大多数GDI函数一样,这个winapi函数属于一类函数,只产生一个“它不工作”的返回代码。它没有给出寻找这个问题的线索。这种怪癖有一个不太好的理由:当你调用DocumentProperties()时,Windows本身几乎不起作用;大部分工作是由打印机驱动程序完成的。在winapi中没有一组用于打印的错误代码。任何事情都是可能的:打印机驱动程序不是细微的代码块。告诉你问题是打印机驱动程序的工作。他们应该通过弹出自己的窗口来做到这一点。从理论上讲,他们是无论如何;激烈的竞争,在那个市场部分没有留下很多钱来支付一个好程序员的工资。

当然,当您从服务中打印时,这是无法工作的。没有任何方法可以看到这样的弹出窗口,这也是微软强烈反对从服务中打印的核心原因。您和客户的IT人员都没有机会诊断问题。有关从服务中使用博客帖子的附加说明,请阅读此PrintDocument

没有人喜欢得到这样的建议,但写在墙上。不要这样做。

票数 19
EN

Stack Overflow用户

发布于 2014-07-17 20:04:05

为了添加到@HansPassant的答案,下面是抛出异常的确切代码:

微软参考源,PrinterSettings.cs

代码语言:javascript
复制
private IntPtr GetHdevmodeInternal(string printer) {
    // Create DEVMODE
    int modeSize = SafeNativeMethods.DocumentProperties(NativeMethods.NullHandleRef, NativeMethods.NullHandleRef, printer, IntPtr.Zero, NativeMethods.NullHandleRef, 0);
    if (modeSize < 1) {
        throw new InvalidPrinterException(this);
    }
    IntPtr handle = SafeNativeMethods.GlobalAlloc(SafeNativeMethods.GMEM_MOVEABLE, (uint)modeSize); // cannot be <0 anyway
    IntPtr pointer = SafeNativeMethods.GlobalLock(new HandleRef(null, handle));

    //Get the DevMode only if its not cached....
    if (cachedDevmode != null) {
        Marshal.Copy(cachedDevmode, 0, pointer, devmodebytes);
    }
    else  {
        int returnCode = SafeNativeMethods.DocumentProperties(NativeMethods.NullHandleRef, NativeMethods.NullHandleRef, printer, pointer, NativeMethods.NullHandleRef, SafeNativeMethods.DM_OUT_BUFFER);
        if (returnCode < 0) {
            throw new Win32Exception();  // <--------
        }
    }
票数 5
EN

Stack Overflow用户

发布于 2009-09-09 21:27:45

这是很难回答没有代码和一个例外,说你一切都好。因此,我将给出一些想法来追踪这个问题。

  1. 在本地打印机上测试它,以确保应用程序工作正常。
  2. 尝试使用记事本或其他类似的方法打印到联网打印机。
  3. 对应用程序正在运行的用户进行双重不三次检查,因为它具有打印网络打印机的权限。
  4. 在另一台联网打印机上测试它(在对该打印机执行2和3之后)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1400783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档