使用Mono Runtime Bundle制作安装包让C#桌面应用程序脱离net framework
在Xamain 未被收购之前,这货monodroid.exe 就是一个打包的绑定。。。无奈 配置环境复杂,未能实现 。。。有mono运行时就行了..不折腾了 玛德
作者:小生、我怕怕
我觉的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的正则表达式得到所有学生列表,并根据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越来越好。
使用Mono Runtime Bundle制作安装包让C#桌面应用程序脱离net framework的更多相关文章
- 对"使用Mono Runtime Bundle制作安装包让C#桌面应用程序脱离net framework"增加说明
http://www.cnblogs.com/basilwang/archive/2011/11/29/2267809.html 想做独立引用的估计都看过这一篇文章,但是因为软件更新,很多地方已经不适 ...
- 解决Inno Setup制作安装包无法创建桌面快捷方式的问题
转自:http://yedward.net/?id=104 昨天想把个java程序做成exe安装软件,然后就去下载了Inno Setup这个软件安装包制作软件,Inno Setup这个软件确实非常好用 ...
- [转]NSIS 制作安装包无法创建桌面快捷方式或无法删除开始菜单项
用户将桌面文件转移了,如: D:\Doc\Desktop ,安装程序后,桌面不会生成快捷方式, 或者卸载后,开始菜单中的文件也不会被删除 NSIS卸载后无法删除开始菜单中的内容原因:因为NSIS中使 ...
- 使用Qt installer framework制作安装包
一.介绍 使用Qt库开发的应用程序,一般有两种发布方式:(1)静态编译发布.这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中.其优势是简单单一,所有的依赖库都集中在一起,其缺点也很 ...
- 使用Qt installer framework制作安装包(不知道是否适合Mac和Linux?)
一.介绍 使用Qt库开发的应用程序,一般有两种发布方式:(1)静态编译发布.这种方式使得程序在编译的时候会将Qt核心库全部编译到一个可执行文件中.其优势是简单单一,所有的依赖库都集中在一起,其缺点也很 ...
- Wix制作安装包
Wix制作安装包,找起资料来很费劲,记录一下: Product.wxs,该文件只能制作出msi形式的安装包,不能做到自动检测framework. <?xml version="1.0& ...
- 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程
一开始让我做安装包的时候,其实我是拒绝的.因为我根本就不会做安装包.查了资料之后,我很懵,很晕,很乱,因为不清晰,不简明,不直白.然而经过一番彷徨的挣扎,我终于发现:制作安装包,谁人都可以!故挥狼毫, ...
- 【原创】VB6.0应用程序安装包的生成(Setup Factory 9.0制作安装包的方法)
VB6.0应用程序安装包的生成,利用其自带的打包工具生成的安装程序很简陋,一点不美观:如果想让自己的应用程序安装的时候显得高大上一点,本教程提供使用Setup Factory 9.0制作安装包的方法. ...
- VS 制作安装包小窥
难得忙里偷闲,看到有关VS制作安装包,按下文小试一把,还行,比不上Installshield. 首先在打开 VS2010 > 文件 >新建项目 创建一个安装项目 XXX 在“目 ...
随机推荐
- HTTP学习实验8-windows添加telnet功能
Windows 添加telnet功能: 控制面板->(查看方式:小图标)->程序和功能->打开或关闭Windows功能->Telnet客户端 Telnet 设置: 打开cmd, ...
- 在SQL中用正则表达式替换html标签
由于数据库的一个表字段中多包含html标签,现在需要修改数据库的字段把html标签都替换掉.当然我可以通过写一个程序去修改,那毕竟有点麻烦.直接在查询分析器中执行,但是MS SQL Server并没有 ...
- 用UBOOT自带loadb命令加载应用程序到SDRAM中运行的方法
S3C44B0开发板中,用UBOOT自带loadb命令加载应用程序到SDRAM中运行的方法 1.开发板说明: 开发板上已有移植好的UBOOT运行. 2.交叉编译工具链为arm-linu-g ...
- motan源码分析三:与spring框架的结合
在本文第一章,分析的demo中使用了代码加载的方式加载了相关的类,但在我们的实际工作中,使用spring来加载相关的类的情况会更多,本文将分析一下motan是如何与spring一起协同工作的,主要的原 ...
- Android 自定义View (四) 视频音量调控
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24529807 今天没事逛eoe,看见有人求助要做一个下面的效果,我看下面一哥们说 ...
- swift实现ios类似微信输入框跟随键盘弹出的效果
封面(图文无关) 为什么要做这个效果 在聊天app,例如微信中,你会注意到一个效果,就是在你点击输入框时输入框会跟随键盘一起向上弹出,当你点击其他地方时,输入框又会跟随键盘一起向下收回,二者完全无缝连 ...
- 理解 B*tree index内部结构
转载请注明出处:http://write.blog.csdn.net/postedit/40589651 Oracle数据库里的B树索引就好象一棵倒长的树.它包括两种类型的数据块:一种是索引分支块,还 ...
- wpf异常:指定的 Visual 不是此 Visual 的上级问题处理解析
WPF在画线的时候,调用Control0.TransformToAncestor(Control1).Transform(new System.Windows.Point(0, 0))方法转换坐标的时 ...
- H1标签使用的七大注意事项
H1标签使用的七大注意事项: 1 每个页面都应该有H1标签,H1标签是每个网页不可缺少的要素. 2 使用H1标签的内容应该简洁明了; 3 H1标签要尽量出现在源文件代码的开头的部分,这样可以让访问者和 ...
- HTTP状态码(HTTP Status codes)简介
HTTP可能大家都熟悉,就是超文本传输协议.浏览器通过HTTP与WEB Server通讯(也有一些其它软件比如IM使用HTTP协议传递数据),把我们的请求(HTTP Request)传递给服务器,服务 ...