【茶包射手日記】檢查.NET程式平台目標(Platform Target)
3 | 27,355 |
一隻.NET寫的排程程式在Windows 2008 x64 OS執行,在連線Oracle資料庫時出現錯誤:
System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at System.Data.OracleClient.OracleInternalConnection.Enlist(String userName, String password, String serverName, Transaction transaction, Boolean manualEnlistment)
at System.Data.OracleClient.OracleInternalConnection.Activate(Transaction transaction)
at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.OracleClient.OracleConnection.Open()
依過去經驗,推測原因為該.NET程式的平台目標(Platform Target)被標註為Any CPU,在x64 Windows平台執行時會在64位元程序(Process)中執行,當它要引用Oracle Client DLL時,在該主機上找不到對應的64位元版DLL,試圖載入32位元版,因而產生錯誤。
要消除茶包,只需將平台目標設為x86重新編譯專案,強迫程式永遠使用32位元程序執行,問題即告排除。不過心生疑問,有沒有方法可以立刻查出某個exe/dll的目標平台被編譯成Any CPU, x86或是x64?
找到.NET Framework SDK中的一個工具程式: CorFlags.exe。CorFlags.exe不但可查詢.NET組件的平台目標設定,甚至能直接修改設定,省去重新編譯的工夫。
先透過實驗觀察不同平台目標組件的旗標。在Visual Studio中依序調整PlatformTarget為Any CPU, x86及x64,分別編譯成BuildTargetAny.exe, BuildTargetX86.exe, BuildTargetX64.exe三個執行檔。
再使用corflags buildtarget*.exe的方法檢視相關旗標,得到結果如下:
H:\Lab\BuildTarget\bin>corflags BuildTargetAny.exe Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. Version : v2.0.50727 CLR Header: 2.5 PE : PE32 CorFlags : 1 ILONLY : 1 32BIT : 0 Signed : 0 H:\Lab\BuildTarget\bin>corflags BuildTargetx86.exe Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. Version : v2.0.50727 CLR Header: 2.5 PE : PE32 CorFlags : 3 ILONLY : 1 32BIT : 1 Signed : 0 H:\Lab\BuildTarget\bin>corflags BuildTargetx64.exe Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. Version : v2.0.50727 CLR Header: 2.5 PE : PE32+ CorFlags : 1 ILONLY : 1 32BIT : 0 Signed : 0
PE, CorFlags, IONLY, 32BIT等旗標的意義可以參考這篇討論。若要將編譯成Any CPU的程式目標平台改為限定x86,可使用以下指令:
CorFlags /32BIT+ BuildTargetAny.exe
將參數改為/32BIT-則可以再還原回Any CPU。至於純x64目標平台的程式由於PE不同(為PE32+,與Any CPU, x86不同),故無法直接使用CorFlags切換,必須重新編譯。
Comments
# by 小黑
黑大,好厲害,怎麼都這麼精準搜尋的到, 不知道都是打那些關鍵字搜尋的阿?
# by 小菜
參考這篇文章 http://theruntime.com/blogs/brianpeek/archive/2007/11/13/x64-development-with-net.aspx 網址掛了 Error 404 - Web app not found.
# by Jeffrey
to 小菜,試試這個:http://stackoverflow.com/a/23614024/288936