[.NET Framework]64位元呼叫32位元元件

[.NET Framework]64位元呼叫32位元元件

今天在噗浪上面剛好demo問了這個問題,我就把我之前的一篇文章也貼過來讓大家參考吧。

轉自:http://www.wretch.cc/blog/JimmyYu/15040779

本來想把一些相關的code也貼一貼,這兩天剛好在整理這份code,或許過兩天我會把一些相關的細節再貼出來給各位參考吧。

前陣子在處理這個頗為棘手的問題,確切的問題是這樣的,我們的Web Application中有一個32位元元件(dll),在64位元電腦上執行時會出現元件無法辨識或BadImageFormatException的錯誤,追究原因乃是因為我們的Web Application執行於IIS上,而IIS在64位元電腦上其執行環境預設是64位元,而同一個process是不能同時執行64位元與32位元元件的。

針對這樣的問題,微軟自然不會沒有解決方案提出,但提出的做法有其缺陷,讓我們先看看微軟的配套解法為何?答案是將IIS透過設定使其執行在32位元的環境下,而在IIS6.0與7.0有不同的設定方法:

<<IIS6.0>>
開始-->執行,輸入cscript.exe adsutil.vbs set W3SVC/AppPools/Enable32BitAppOnWin64 1,但此設定是針對整個IIS,若在IIS上各有32與64位元的網站要執行,就會有問題。


<<IIS7.0>>
可針對每個應用程式集區進行32/64的設定,設定上較靈活,但限制是IIS7.0只能安裝在Windows Server 2008之後的版本,先前的版本並無法升級成7.0。

但以上只針對可架設在IIS上的Web Application,如果是一般的Windows程式怎麼辦?答案是在建置時選擇要建置成x86或x64的執行程式,如果選擇了x86,在64位元電腦上執行時,OS會自動模擬一個32位元的執行環境來run,這時候這個程式就可以呼叫32位元的元件,但無法呼叫64位元的元件,反之亦然;而在建置的選項中有一個Any CPU則代表這個程式會自動選擇適合的執行環境,在32位元上以32位元程式執行,在64上則以64程式執行,如果選擇了Any CPU,你要在64位元電腦呼叫32位元的元件將不可行。

從以上看來,如果我要在64位元的環境執行32位元的元件,以Web Applicaiotn來說有幾個方法:
1.IIS降為32位元執行
2.改寫32位元元件
3.使用out-of-process的方式由另一個元件來呼叫32位元元件

方法1因為會影響到其他系統,因此不可行(除非都是IIS7.0),方法2則因為該元件的source已不可考,想翻寫也變得不可能,所以最後考慮使用方法3。

不管是Web/Window程式,當我們使用reference或者DllImport的方式呼叫dll,實際上都是將這個dll載入到目前的執行環境中(x86/x64),所以只要載進來的元件與目前的執行環境有衝突時,就會發生錯誤,但如果我們今天呼叫的是一個Console程式、Window Form程式、Windows Service,這些程式就會另外啟動一個process,而這個process是與呼叫端的執行環境相獨立。

本來的執行環境是這樣:IIS(x64)-->元件(x86)    出現錯誤
現在我改成:IIS(x64)-->Windows Service(x86)-->元件(x86)     成功

這個問題花了兩三天的時間,而其中的關鍵技術是.net remoting,這部分要用圖解會比較清楚,但我今天時在懶的貼圖,就這樣吧。

游舒帆 (gipi)

探索原力Co-founder,曾任TutorABC協理與鼎新電腦總監,並曾獲選兩屆微軟最有價值專家 ( MVP ),離開職場後創辦探索原力,致力於協助青少年培養面對未來的能力。認為教育與組織育才其實息息相關,都是在為未來儲備能量,2018年起成立為期一年的專題課程《職涯躍升的關鍵24堂課》,為培養台灣未來的領袖而努力。