2009-09-09 157 views
10

我想在C#.NET 3.5的應用程序打印到網絡打印機,並獲得此異常完成是什麼造成的,它如何解決?PrintDocument.Print結果Win32Exception將操作成功

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() 
  • 帳戶有權限使用網絡打印機進行打印。爲每個人打印權限。
  • 打印機已被刪除並重新創建。
  • 直接後臺VS打印到打印機的設置已經切換兩種方式。
  • 機器上的其他打印機工作正常
  • 網絡上的其他客戶端和同一臺機器上的應用程序可以正常打印到本打印機。

要縮小這個問題的時候,我已經創建了一個簡單的控制檯應用程序。以普通用戶身份運行應用程序打印。當運行作爲服務帳戶,它犯錯服務帳戶

enter image description here

分辨率我的問題是卸載,導致該問題的驅動程序,並安裝一個較舊的驅動程序。

+1

我以前得到過這個錯誤 - 錯誤信息是真的讓人誤解。我想你已經完成了,但如果你不發佈一些代碼,我會回覆你。 – Brandi 2010-04-07 16:06:52

+0

@ p.campbell抱歉,我沒有。我記得缺乏有關這些主題的文檔,感到非常沮喪,所以對不起,我無法提供更多幫助。當時我發佈了幾個關於半相關打印主題的舊問題,但不確定這些問題是否相關,或者您是否已經檢查了這些問題。 – Brandi 2014-07-13 21:54:31

回答

1

這很難,沒有代碼,並說你一切都OK了異常回答。所以我只是給一些想法,以追查問題

  1. 測試它在本地打印機上,以確保應用程序的工作。
  2. 嘗試使用記事本或類似的東西打印到聯網的打印機
  3. Double nay triple檢查應用程序正在運行的用戶是否具有打印到網絡打印機的權限。
  4. 測試它在另一聯網的打印機(在執行圖2和3爲該打印機之後)
17

神祕消息由在.NET Framework內的PInvoke代碼中的錯誤引起的。失敗的基礎winapi調用是DocumentProperties() function。它的PInvoke的聲明如下所示:

[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的其他注意事項,請閱讀blog post

沒有人喜歡得到像這樣的建議,但寫在牆上。 不要這樣做

5

要添加到@ HansPassant的答案,這裏是有問題拋出異常確切的代碼:

微軟參考源,PrinterSettings.cs

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(); // <-------- 
     } 
    } 
0

我也有這個問題。在我的情況下,我使用單獨的線程來打印報告,並通過「ManualResetEvent」將其與主線程同步。 (我已經開發了這種方式,因爲.Net的力量將打印邏輯分成「PrintPage」方法......)。

由於打印機驅動程序和此多線程環境之間的不兼容性(我無法解釋源代碼)發生錯誤。

我通過將我的打印邏輯方法簽名從「void」更改爲「IEnumerable」來解決問題,並突破了產量返回,這種方法類似於Unity3d遊戲引擎的「CoRoutines」。這樣,就沒有必要創建多個線程,並且我的打印代碼得到組織。

+0

不知道爲什麼這是downvoted,但你剛剛幫我解決了我一直在努力的一個問題。 出於測試目的,我在UI線程上啓動了我的打印,它確實工作,返回從另一個線程啓動打印,並將打印機驅動程序更新爲HP的最新正式版本,現在可以使用。 我以前使用惠普的通用PCL6 6.2.6。該驅動程序不喜歡被稱爲多線程environement。 – 2017-12-07 19:42:37

+0

6.2.1,對不起。 惠普通用打印PCL 6(v6.2.1) – 2017-12-07 19:52:43