在Xamain 未被收購以前,這貨monodroid.exe 就是一個打包的綁定。。。無奈 配置環境複雜,未能實現 。。。有mono運行時就好了..不折騰了 瑪德javascript
做者:小生、我怕怕php
網址:http://www.apkbank.nethtml
我覺的MS的.net方案其實很不錯。C#呢,用如今流行的話來講「很給力」!ios
可是.net版本衆多。並且.NET Framework框架很大。拖着一個大大的.net Framework老是讓人很鬱悶。c++
我也碰到了這個讓人鬱悶的問題。web
在網上找呀找呀。找到另外一個.NET Framework 替代方案。Mono。正則表達式
下載地址爲:http://www.go-mono.com/mono-downloads/download.htmlc#
Mono2.10.2版本支持.net 2.0至4.0版本。windows
下載回來後安裝一下,我傻了竟然有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.五、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
以前有一個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的正則表達式獲得全部學生列表,並根據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上。個人代碼檢查經過,但在後繼過程發現訪問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愈來愈好。