使用Mono Runtime Bundle製作安裝包讓C#傳統型應用程式脫離net framework

來源:互聯網
上載者:User

標籤:

在Xamain 未被收購之前,這貨monodroid.exe  就是一個打包的綁定。。。無奈 配置環境複雜,未能實現 。。。有mono運行時就行了..不折騰了 瑪德

讓C#程式獨立運行(脫離 .NET Framework運行,綠色運行)部落格分類:
     
  • dotnet
.netwinformc# 

小生、我怕怕

網址:http://www.apkbank.net

 http://www.17zouguo.net

我覺的MS的.net方案其實很不錯。C#呢,用現在流行的話來說“很給力”!

但是.net版本眾多。而且.NET Framework架構很大。拖著一個大大的.net Framework總是讓人很鬱悶。

我也碰到了這個讓人鬱悶的問題。

在網上找呀找呀。找到另一個.NET Framework 替代方案。Mono。

為:http://www.go-mono.com/mono-downloads/download.html

Mono2.10.2版本支援.net 2.0至4.0版本。

下載回來後安裝一下,我傻了居然有336M。而且Mono的居然方式是命令列的。仍然讓人很鬱悶。

算了,既然安裝了。找找資料吧。

終於看到了前人的工作結晶。

Mono運行C#程式所要的庫資源其實不多。

 

只要C:\Program Files\Mono-2.10.2\bin目錄下的。(以下均以C:\Program Files\Mono-2.10.2目錄為根目錄)

mono.exe,mono-2.0.dll

lib\mono\.net版本號碼\mscorlib.dll。我這裡用的是.net 2.0版本。

lib\mono\gac\目錄下的必要庫檔案。WinForm程式只要這5個庫就行了。

 

每個庫檔案下,又有自己的.net版本號碼。如果用的是.net 2.0那麼4.0.0.0那個目錄就可以刪除,如果你想問為什麼沒有3.0、3.5的庫。答案是3.0和3.5用的是2.0的庫。而1.0的庫由於年代久遠,Mono2已經不支援了。如果需要的話,可以下載Mono早期的版本。

另外我發現庫檔案下,有同名的.mdb檔案。

 

那個.mdb檔案刪除掉對程式沒什麼影響。所以通通刪除掉。

 經過層層刪除,最後剩下的那幾個檔案,加起來也就8M多點。而程式一點問題也沒有。完美運行!

 

發行軟體的時候用RAR壓縮一下,程式只有3M多。很完美了!

可是我怎麼知道。。我的程式具體要用到哪些庫呢?

答案是:不知道。去記程式要用到哪些庫太累了。我才不會去記呢。我有一個偷懶的辦法。建立一個檔案夾,先將不變的檔案放好。bin目錄下的mono.exe,mono-2.0.dll,lib\mono\.net版本號碼\mscorlib.dll。最後將Mono下lib\mono\gac中所有的庫檔案拷貝過來。運行編譯好的C#程式。現在可以開始瘋狂的刪除了,碰到不能刪除的檔案,剩下的就是我們的程式要用的庫了。此方法簡單高效,百試不爽。

 

但是接下來還有個問題,Mono那個討厭的命令列。還有如果人家電腦上裝了.net庫呢?用MS自家的.net不是更好嗎?於是我參考Mono官網,用C和windows api寫了一個.net的引導程式。可以根據用設定來選擇.net版本,如果客戶電腦已經安裝使用者指定版本,則優先使用MS的.net,如果不存在則用Mono引導程式。

這個引導程式使用config.ini做為設定檔。

 

C#_Version=2.0                    //.net版本號碼,共有4個值:2.0、3.5、4.0C、4.0F

C#_AppName=MyBooks.exe   //開機前的應用程式名稱

這個引導程式,在32位XP下使用VS 2008編譯。因為是用windows api編寫,沒有額外的庫。所以理論上32位的系統應當都能使用,64位的沒試過。這個引導程式測試.net 2.0項目和.net 4.0項目都沒問題。這個程式直接調用了mono-2.0.dll。所以Mono.exe也就沒用了。下面給出我的測試專案,直接運行monologin.exe即可。效果我還是很滿意的。同時歡迎交流!

附件下載:
c#引導項目.rar 3.17MB

 

  • 9af63fe1c40580238a33d62f27b0ef3020110801150801.rar (3.2 MB)
  • 下載次數: 847
  • 查看圖片附件
 

 

 

之前有一個C#版本和ios版本(支援下載學生名單,點名等更多功能,該版本未上app store)的教輔助手協助學校老師提交成績到教務系統(浙大正方web版),一直打算用mfc寫一個vc++版本的可以方便的在未安裝net framework的電腦上使用,前幾天看到一篇文章再談為什麼要使用MONO  ,既然Unity3D遊戲(mono核心)可以單獨打包脫離net framework,那我的教輔助手一定可以。可是在網上找了一下,中文資料很少,沒有討論具體技術細節的文章( 讓C#程式獨立運行(脫離 .NET Framework運行,綠色運行) 是我在移植完成後寫教程的時候看到的文章,我的思路和他不太一樣,我使用了mkbundle)。

教輔助手雖然功能比較簡單,但是比hello world還是有技術含量的。我在測試打包的時候使用hello world沒有問題,能夠脫離net framework正常顯示,但如果更複雜的功能和代碼以及引入第三方類庫的話,到底有沒有問題,我心裡沒底。 實際在我移植的過程中確實碰到很多問題,這個是簡單的測試hello world移植所解決不了的。因此我在解決問題後,寫下此文記錄一下。

先說一下教輔助手的功能(由於工作原因無法放出該程式碼),簡單點說就是要匯入excel成績表並直接提交到教務系統的頁面中,為清楚列表如下

1 匯入excel成績表

2 提交至web教務系統

3 視覺化介面操作

使用的相應技術

1 使用System.Data.Oledb訪問excel並將取得內容放入System.Data.DataSet

2 使用System.Net.HttpWebRequest類比教務系統登入(該系統使用cookieless方式,所以需要先訪問一次得到url中產生的sessionid),然後填入課程相關資訊,類比post提交,使用System.Text.RegularExpressions的Regex得到所有學生列表,並根據DataSet內容產生新的Post資訊,再次利用post方式提交到教務系統中。

3 使用Winform視窗形式

相關軟體

window7 professional  64bit

Cygwin

net 2.0/3.5/4.0 framework

mono 2.10.6

gtk 2.12

MonoDevelop 2.8.2

下面說一下我的具體過程

1 首先使用Mono Migration Analyzer(MoMA) 檢查已有代碼是否可以移植到mono上。My Code檢查通過,但在後繼過程發現訪問excel功能報錯,原因後面會說 。個人感覺MoMA不是很靠譜。

2 使用mono編譯教輔助手源碼。 這裡我使用了MonoDeveloper工具,當然也可以使用類似csc.exe的mcs.exe命令列編譯方式。不過由於MonoDevelop沒有winform的設計器,而且winform是Win32技術,相容性在Linux下不是很好, mono建議使用GTK#這種第三方的Form技術來做UI,我這裡為了使用MonoDeveloper把winform的代碼用gtk重寫了,用了一個小時吧,代碼分層比較好,比較容易剝離。當然如果你習慣csc.exe的命令列方式,而且你的移植後的程式只在window下面運行,那你可以使用mcs.exe並且不需要gtk重寫(未嘗試此種方式,感覺應該可行,如果哪位朋友有過相關經驗,請告知)。

使用MonoDevelop要求安裝mono和gtk,這裡要特別注意的是MonoDevelop可以選擇使用net framework還是mono進行編譯,開始我沒有注意我在MonoDevelop下使用net framework編譯運行成功,打包後在mono下運行總是出問題,而且出錯資訊始終為空白,浪費了大量時間。

3 在MonoDevelop下選擇mono,編譯成功後運行失敗,報libgda錯誤,這裡解釋下問題出現的原因mono下的ole db應該是封裝了libgda,而且mono oledb 支援Sql Server,Oralcle,MySql,SqlLite,不支援Excel;至於為什麼不支援Excel,很簡單Excel實際上是通過COM訪問的(這個是微軟的,*nix下不支援)。解決的辦法就是不用ole db,於是換用CodePlex上的ExcelDataReader,支援mono,ok。

4 MonoDevelop運行時正常而打包後運行時System.Net.HttpWebRequest出錯。在啟動並執行時候發現HttpWebRequest無法正常工作,甚至簡單的HttpWebRequest.Create(開始懷疑過是cookie container以及url路徑問題,均排除,痛苦過程不表)。解決的辦法是將machine.config檔案一併打包。

參見Issue with embedding machine.config 實際上我們可以從machine.config發現相關HttpWebRequest的配置資訊,該檔案路徑:mono安裝目錄\etc\mono\mono版本號碼\machine.config。

5 mkbundle打包。 實際上4和5可以一併說,4中描述的問題導致我頻繁的測試mkbundle,嘗試載入不同的dll。一度懷疑是打包時dll未正確包含所致,將所需的所有類庫lib(system.web.dll、system.net.dll、gac目錄等)一併拷貝到運行目錄下,仍報錯且無任何錯誤提示,抓狂。這裡犯了低級錯誤檢討一下,mono官網提到mkbundle是一種static linker方式,會將所用到的dll連同應用程式一併embed到一個exe檔案中,實際上mkbundle後不再需要類庫的dll。

mono的mkbundle使用Unix-like toolchain,所以要在window下使用mkbundle需要安裝cygwin(同樣痛苦的過程),選擇gcc-mingw, mingw-zlib, pkg-config,zlib(注意不要選gcc全部安裝,網上說有問題我試過也是如此,完全卸掉gcc只選擇gcc-mingw), 然後配置cygwin的~/.bashrc檔案中配置

export PATH=$PATH:/cygdrive/c/Mono-2.6.1/bin 
export PKG_CONFIG_PATH=/cygdrive/c/Mono-2.10.6/lib/pkgconfig

這裡參考Can not compile simple C# application with mkbundle 非常詳細

結合我的實際使用說明一下:

無法單獨使用mkbundle –o  –-deps 的方式使用mono runtime, 因為mkbundle有一個bug,詳見 New: Mkbundle Fails Due To Missing Reference To G_utf16_to_utf8 (2.8.0, Windows XP) 如果直接使用會報

temp.c: In function `main‘: 
temp.c:170: warning: implicit declaration of function `g_utf16_to_utf8‘ 
temp.c:170: warning: assignment makes pointer from integer without a cast 
temp.c:185: warning: assignment makes pointer from integer without a cast 
/tmp/ccgvpEs0.o: In function `main‘: 
/cygdrive/d/paco/jpegp4d-deploy/temp.c:170: undefined reference to 
`_g_utf16_to_ 
utf8‘ 
/cygdrive/d/paco/jpegp4d-deploy/temp.c:185: undefined reference to 
`_g_utf16_to_ 
utf8‘ 
collect2: ld returned 1 exit status 
[Fail]

因此採用mkbundle –c(2012-1-12 更新 在cmd下執行)和gcc -mno-cygwin(2012-1-12 更新 在cygwin下執行)的結合的方式

以下引自Can not compile simple C# application with mkbundle ,感謝Lavir the Whiolet

    • 執行: "mkbundle -c -o host.c -oo bundle.o --deps YourAssembly.exe <additional arguments>". 可選-z進行壓縮. 完成後得到host.c和bundle.o檔案.
    • 在host.c檔案中移除_WIN32。增加#undef _WIN32如下:

      #ifdef _WIN32
      #include <windows.h>
      #endif

      得到:

      #ifdef _WIN32
      #include <windows.h>
      #endif
      #undef _WIN32
    • 執行: "gcc -mno-cygwin -o ResultantBundle.exe -Wall host.c`pkg-config --cflags --libs mono-2|dos2unix` bundle.o <additional arguments>". 如果你mkbundle 加了-z參數, 你必須在這步增加 –lz

我的補充

     (1) 執行mkbundle是需要embed machine.config的話 增加—machine.config C:\Mono-2.10.6\etc\mono\4.0\machine.config,參考mono project bundles

     (2) 如果引入第三方dll的話(比如我使用了第三方ExcelDataReader的excel.dll), 應該加到mkbundle 的<additional arguments>位置,參考Embedding a JavaScript interpreter with Mono

以我的mkbundle為例

     mkbundle –c –o host.c –oo bundle.o –deps myProgram.exe Excel.dll  --machine-config C:\Mono-2.10.6\etc\mono\4.0\machine.config

更新(2012-01-12):

mkbundle -c -o host.c -oo bundle.o --deps MonoTA.exe Excel.dll -z --machine-config C:\Mono-2.10.6\etc\mono\4.0\machine.config

6 發布 

   產生的exe檔案已經embed mono runtime了,我的應用程式原來32k,使用-z壓縮產生後是5MB,有點大不過可以接受。但要脫離net framework在window上執行,還需要調用幾個檔案,羅列如下(針對mono4.0,我一個個找的,是不是可以做個工具自動尋找依賴?)

freetype6.dll 
glibsharpglue-2.dll 
gtksharpglue-2.dll 
intl.dll 
libatk-1.0-0.dll 
libcairo-2.dll 
libexpat-1.dll 
libfontconfig-1.dll 
libgdk_pixbuf-2.0-0.dll 
libgdk-win32-2.0-0.dll 
libgio-2.0-0.dll 
libglib-2.0-0.dll 
libgmodule-2.0-0.dll 
libgobject-2.0-0.dll 
libgthread-2.0-0.dll 
libgtk-win32-2.0-0.dll 
libpango-1.0-0.dll 
libpangocairo-1.0-0.dll 
libpangoft2-1.0-0.dll 
libpangowin32-1.0-0.dll 
libpng14-14.dll 
mono-2.0.dll 
MonoPosixHelper.dll 
zlib1.dll

總共16.9MB

7 後記

個人感覺,雖然過程曲折了點,但使用mono runtime讓軟體脫離net framework是完全可行的,而且應該是可以用到生產環境的,也希望mono越來越好。

使用Mono Runtime Bundle製作安裝包讓C#傳統型應用程式脫離net framework

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.