windows 編譯版本異常處理


今天在編譯一個Windows Form程序時.突然發現一個問題.在本機開發環境[X64位]能夠很好調用.等打包安裝后放到32位機器是突然發現提示一個錯誤如下:

未命名

具體異常信息如下:

有關調用實時(JIT)調試而不是此對話框的詳細信息,
請參見此消息的結尾。

************** 異常文本 **************
System.DllNotFoundException: 無法加載 DLL“Win32Project1.dll”: 找不到指定的模塊。 (異常來自 HRESULT:0x8007007E)。
   在 AndroidSkinTool.UnsafeNativeMethods.getKey()
   在 AndroidSkinTool.Forms.FormMain.btnRefresh_Click(Object sender, EventArgs e) 位置 d:\C#Workspace\SkinToolCode_V6.1\Forms\FormMain.cs:行號 2708
   在 System.Windows.Forms.Control.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.OnClick(EventArgs e)
   在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   在 System.Windows.Forms.Control.WndProc(Message& m)
   在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
   在 System.Windows.Forms.Button.WndProc(Message& m)
   在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

其實在應用程序中實現一個很簡單的功能. 在。net程序中C#通過Dllimport方式來調用C++ DLL庫.傳遞一個字符串而已. 而出現System.DllNotFoundException異常的原因主要存在如下幾個問題:

首先需要確定調用C++ DLL是否正確導出.因為可以再開發環境正常運行.可見DLL已經成功導出.成功導入后.需要確認在.NET環境導入的方式是否正確.在導入前需要引用如下庫:

   1:  using System.Runtime.InteropServices;

導出方法:

   1:  [DllImport("WindowsEntity1.dll",EntryPoint= "TA_Init3",CallingConvention = CallingConvention.StdCall)]
   2:  public static extern int TA_Init3(string IP, Int16 port,ushort SysCode, ushort TerminalNo);

如果導出方式也正確.還提示如上問題的話.這個時候我們則需要進一步分析調用C++DLL 有沒有引用其他庫或存在其他依賴.采用dependency worker工具分析當前windowsEntity1 DLL引用依賴項 如下:

QQ截圖20130530150203

you see.可以看到當前win32Project1.DLL主要有兩個依賴項 MSVCR110.DLL和KEREML32.DLL. 而MSVCR110在當前操作系統確實才導致了當前開始運行提示DLLNotFoundException異常信息.我們可以再項目Realse目錄下添加改DLL或是把改DLL拷貝到System 32下保證系統環境中可見. 發現DLLNotFoundEXception異常則消失了.應用程序正常運行.這里需要注意一點. 在通過.NET 調用C++ DLL 時. 應用會首先在System 32系統環境查找是否具有MSVCR110.DLL依賴項.如果沒有則繼續在安裝目錄下尋找.如果兩邊都沒有找到則會爆出DllNotFoundException異常信息. 因此簡單方式有兩種. 第一可以通過代碼在調用注冊該DLL信息. 另外可以直接把依賴的MSVCR110.DLL拷貝到realse目錄下即可.

另外除了以上情況.還有一種特殊情況是.看運行環境是否安裝了VC Runtime library. 類似在VS2012 環境下默認是安裝的. 有些機器沒有安裝或是采用VC6.0編譯的DLL.所以為了免去打包安裝的麻煩.可以通過安裝相應VC運行時庫或者直接把幾個相應版本運行時的庫文件直接放到可執行程序里面進行發布,從而省卻安裝過程. 這是一個比較直接的解決方案.

為了保證能夠兼容32和64 兩個平台.我在調用.NET程序設置編譯選項為AnyCpu方式.卻發現。net拋出如下異常信息:

Unhandled Exception:

System.BadImageFormatException: Could not load file or assembly 'SourceCode.HostClientAPI, Version=4.0.0.0, Culture=neutral, PublicKeyToken
=16a2c5aaaa1b130d' or one of its dependencies. An attempt was made to load a program with an incorrect format.
File name: 'SourceCode.HostClientAPI, Version=4.0.0.0, Culture=neutral, PublicKeyToken=16a2c5aaaa1b130d'

也就是你現在看到的System.BadImageFormatException異常.針對這個問題.官方MSDN上說的很詳細.Visual Studio的編譯選項 build中的platform存在有3個選項X64、Any CPU和x86。X86表示只能在32位環境下運行,X64表示只能在64位環境下運行,Any CPU表示你的程序集可以根據環境變化適應32位還是64位,但是如果你的程序集依賴於一個x86選項編譯的程序集類似調用一個win32 C++ DLL,哪么你的程序集只能選擇X86進行編譯,而不能選擇Any CPU編譯,如果使用Any CPU編譯.則這個時候會拋出System.BadImageFormatException異常信息.

而真正的原因是.如果你采用Anycpu方式進行編譯.那么在64位機器默認的運行就是64位的,通常這情況是assembly需要調用一個32的COM庫,只要用x86編譯,那么程序就是以32位的程序,依靠wow64來運行的,就可以在64位系統上運行。所以,如果assembly需要使用win32庫的話。正確的做法是把編譯的選項設置X86來編譯.即可.唯一點需求.保證調用的C++ DLL編譯版本和調用版本一致才是原則所在.這樣一來在32和64位則不會爆出如上異常問題.

在官方文檔說了兩個意外情況. 也是值得參考的.

如果您的應用程序使用了 32 位組件,請確保該應用程序始終采用 32 位應用程序的運行方式。

如果應用程序項目的“平台目標”屬性設置為 AnyCPU,則編譯后的應用程序在 64 位或 32 位模式中均可運行。如果采用 64 位應用程序運行方式,則實時 (JIT) 編譯器便會生成 64 位本機代碼。如果應用程序依賴於某個 32 位托管組件或非托管組件,則在 64 位模式中無法加載該組件。若要糾正此問題,請將項目的“平台目標”屬性設置為 x86,然后重新編譯。

確保未使用利用其他 .NET Framework 版本創建的組件。

如果使用 .NET Framework 1.0 或 .NET Framework 1.1 開發的應用程序或組件嘗試加載使用 .NET Framework 2.0 SP1 或更高版本開發的程序集,或者使用 .NET Framework 2.0 SP1 或 .NET Framework 3.5 開發的應用程序嘗試加載使用 .NET Framework 4 開發的程序集,便會引發此異常。 BadImageFormatException 異常可能會報告作為編譯時錯誤,或在運行時可能會引發該異常。有關示例,請參見 BadImageFormatException 類

參考資料:

關於疑難異常解答:system.BadImageFormatExcetpio.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM