发现一个不错的网站,转载一篇文章方便查看
 
===============================================
    作者:宇内流云

最让.NET程序员苦恼的是,辛辛苦苦写出来的.NET程序,需要客户机上安装了.NET才能运行。仅为一个小小的应用程序去下载上百兆的.NET安装包,还得把它老老实实安装到客户机上,并占掉数百兆磁盘空间,这无疑是一件得不偿失的事情。.NET程序的这个弱点,也是影响.NET应用程序普及和价值的一个重要因素。
    所谓“独立运行”,是指.NET应用程序脱离完整的.NET运行环境,像c语言编译的程序那样,在操作系统上直接运行。简单地说就是:客户电脑无需安装任何版本的.NET框架,你的.NET程序照样可以在他的电脑或服务器上运行。
    .NET程序独立运行的基础是mono运行时以及它的程序集。mono是什么呢,mono是一款开源、免费、可定制的跨平台.NET运行环境,同时,它还包含了一系列具有重要意义的实用工具,当前最新的版本号是3.0.10,本文所采用的mono,即是这个版本号的windows版。

那么,到底怎么才能让你的.NET程序无障碍地在没有安装.NET平台的客户机“独立运行”呢,下面直奔主题。

一,建立跨平台的.NET环境与编译环境:
    1、下载并安装mono的windows版,建议将它安装到c:\mono文件夹中。
    2、安装cygwin。
       A、建议将它安装到c:\cygwin文件夹中。
       B、安装时,请将mingw-gcc、mingw-zlib、pkg-config、libiconv这几个组件选上,这是将.NET程序转化为本地程序的必要的编译环境。

二,启动cgywin并设置环境变量:
    1、点击开始菜单或桌面上的cygwin图标,启动且进入cygwin环境。
    2、输入下面的命令,设置或修改必要的环境变量:
       export PKG_CONFIG_PATH=/cygdrive/c/mono/lib/pkgconfig
       export PATH=$PATH:/cygdrive/c/mono/bin

三,将你的.NET程序转化为“独立程序”

请注意,这是本文的关键所在,很多地方的操作都有别于其它网文和mono官网所介绍的操作技术。

1,复制文件。把需编译的.NET EXE文件和对应的DLL文件复制到你在cygwin的工作文件夹中,如果你的windows用户名是xyz,那么这个文件夹就是 c:\cygwin\home\xyz\,(这一步不是必须的,如果你不怕麻烦而愿意多打字的话)。

2,转换与打包。通过下面的命令,将.net程序和类库打包并得到一个c程序源码(假设你需要转换的.NET文件是a.exe)。
    mkbundle -c -o b.c -oo b.o a.exe -z
    或者:
    mkbundle -c -o b.c -oo b.o a.exe aa.dll c:\\mono\\lib\\mono\\4.5\\mscorlib.dll -z
    或者:
    mkbundle -c -o b.c -oo b.o --dept a.exe -z

3,修改得到的c文件:
    这是本文的精华所在。
    为什么要修改这个c文件,很简单:
    A,不希望与exe文件相关的类库全部打包到一个文件中,否则,太浪费,而且影响启动速度。
    B,这个c文件是目标程序的关键文件,我希望在中间加上自己的东西,让我的程序如虎添翼。
    C,我程序要在中文、日文这样的含有非英文字母的文件夹中运行。

3.1,需要添加和修改的内容:
    A,用VS或记事本打开b.c,把下面的代码复制到main函数之前,作一个准备。

#include <dir.h>
    #include "/usr/include/iconv.h"
    int gbk_utf8(char *inbuf,int inlen,char *outbuf,int outlen){
        iconv_t cd;
        char **pin = &inbuf;
        char **pout = &outbuf;
        cd = iconv_open("utf-8","gbk");
        if (cd == 0) return -1;
        memset(outbuf, 0, outlen);
        if (iconv(cd, pin, &inlen, pout, &outlen) == -1) return -1;
        iconv_close(cd);
        return 0;
    }

B、在main函数中,找到下面这两行并注释或删除掉:
   if (config_dir != NULL && getenv ("MONO_CFG_DIR") == NULL)
      mono_set_dirs (getenv ("MONO_PATH"), config_dir);
   
   C、接着,就在这行下边,即“mono_mkbundle_init”一行之前,输入下边的代码:

const char* lib = "\\lib";
    const char* etc = "\\etc";

char p[strlen(argv[0])];
    wsprintf(p,"%s",argv[0]);

int l = 0;
    l = strlen(p);
    for(i=l-1; i>0; i--){
        if(p[i] == '\\'){
            p[i] = '\0';
            break;
        }
    }

l = strlen(p) + strlen(lib);
    char s_lib[l];
    wsprintf(s_lib, "%s%s", p, lib);

l = strlen(s_lib);
    char* s_lib_utf8 = (char*)malloc(l*2);
    memset(s_lib_utf8, 0, l*2);
    gbk_utf8(s_lib, l, s_lib_utf8, l*2);

l = strlen(p) + strlen(etc);
    char s_etc[l];
    wsprintf(s_etc, "%s%s", p, etc);

l = strlen(s_etc);
    char* s_etc_utf8 = (char*)malloc(l*2);
    memset(s_etc_utf8, 0, l*2);
    gbk_utf8(s_etc, l, s_etc_utf8, l*2);

mono_set_dirs(s_lib_utf8, s_etc_utf8);

接着在mono_mkbundle_init一行之后加入一行:
    chdir("c:\\");

最后,找到下面三行
    #ifdef _WIN32
    #include <windows.h>
    #endif
    并在“#endif”后加入一行:
    #undef _WIN32

改完了,存盘退出。
    (有人会说“输入这么多,为什么不写个函数以方便我将来复用?”,我说,这不是我的事。)

3.2,编译:
    用下面这个命令生成你的目标文件“b.exe”。
    gcc -mno-cygwin -o b.exe -Wall b.c `pkg-config --cflags --libs mono-2|dos2unix` b.o -lz -liconv

四,程序、类库、配置文件的组织:
    这一步,是为你的程序安一个家,让它真的能跑起来。

1,在某个盘,比如D盘,建个文件夹,比如是“myapp”
    把刚才编译得到的目标文件b.exe复制到D:\myapp文件夹中。
    同时把c:\mono\bin\文件夹中的mono-2.0.dll、zlib1.dll、iconv.dll复制到d:\myapp中。

2,组织类库
    在“d:\myapp”文件夹中,建lib和etc两个子目录。
    在lib文件夹中,建名叫“mono”的文件夹。
    在d:\myapp\lib\mono文件夹中,根据你.NET程序集版本号建一个文件夹,名字就是版本号,比如“4.5”,当然,你也可以把2.0、4.0也建好。
    如果你没有将mscorlib.dll打包到.EXE中,请将c:\mono\lib\mono\4.5\mscorlib.dll,复制到 d:\myapp\lib\mono\4.5这个文件夹中。
    在d:\myall\lib\mono文件夹中,建一个名为gac的文件夹,这个文件夹是用来放你的程序需要的mono版.NET类库的。
    放些什么?放你的exe、dll文件中引用到的那些程序集的库文件(如果你已经把这些文件打包到了.exe中,那么你就不需要放任何文件)。
    比如,你引用了System名字空间,那么,将c:\mono\lib\mono\gac文件夹下的System文件夹复制到D:\myapp\lib\mono\gac中就行了。

3,组织配置文件
    把c:\mono\etc文件夹中的“mono”文件夹复制到d:\myapp\etc文件夹中。
    用写字版打开config文件,找到并删除下列三行:
    <dllmap dll="gdiplus" target="/tmp/install/lib/libgdiplus.so" />
    <dllmap dll="gdiplus.dll" target="/tmp/install/lib/libgdiplus.so" />
    <dllmap dll="gtkhtml-3.0" target="libgtkhtml-3.8-15.dll"/>

通过上面的几个步骤,你的程序已经变成了可以独立运行的程序了,你把d:\myapp这个文件夹压缩打包,然后解压到没有安装.net的电脑上,试试。

[转].NET程序在windows操作系统上独立运行的技术要点的更多相关文章

  1. Windows操作系统上各种服务使用的端口号, 以及它们使用的协议的列表

    Windows操作系统上各种服务使用的端口号, 以及它们使用的协议的列表 列表如下 Port Protocol Network Service System Service System Servic ...

  2. django程序在windows服务器上发布

    django程序在windows服务器上发布 参考文献:https://www.cnblogs.com/djangocn/p/10227006.html 1.安装 IIS 和 GCI 打开服务器管理器 ...

  3. Windows OS上安装运行Apache Kafka教程

    Windows OS上安装运行Apache Kafka教程 下面是分步指南,教你如何在Windows OS上安装运行Apache Zookeeper和Apache Kafka. 简介 本文讲述了如何在 ...

  4. 在英文Windows操作系统上使用SQL Server Management Studio(SSMS)导入Excel 97-2003文件时报错:Failure creating file

    今天在公司服务器上使用SQL Server Management Studio(SSMS)导入Excel 97-2003文件(.xls)时报错: Failure creating file. (Mic ...

  5. 【转】如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件

    问题描述: 用VS2013写好一个程序,在本机上运行一切正常.但是如果直接把exe文件放到另一台机器上用,则会出现: Windows XP:不是一个正常的win32程序 Window 7:缺少msvc ...

  6. Windows操作系统电脑的运行代码大全

    CMD命令使用方法:开始->运行->键入cmd.或者win键+R->键入cmd gpedit.msc—–组策略 sndrec32——-录音机 Nslookup——-IP地址侦测器 e ...

  7. C++程序在Windows平台上各种定位内存泄漏的方法,并对比了它们的优缺点

    一.前言 在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准.而在W ...

  8. tensorflow在windows操作系统上的安装

    在电脑上安装PyCharm和Python3,然后把Python3的安装路径写进系统变量里,Python安装完之后, https://bootstrap.pypa.io/get-pip.py,把这页的代 ...

  9. java程序在windows系统作为服务程序运行

    Java程序很多情况下是作为服务程序运行的,在Un*x 平台下可以利用在命令后加“&”把程序作为后台服务运行,但在Windows下看作那个Console窗口在桌面上,你是否一直担心别的同时把你 ...

随机推荐

  1. 【转】web测试方法总结

      一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号.禁止直接输入特殊字符时 ...

  2. C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)

    介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...

  3. JavaScript入门(10)

    一.Window对象 window对象是BOM的核心,window对象指当前的浏览器窗口 window对象方法 二.JavaScript计时器 在JavaScript中,我们可以在设定的时间间隔之后来 ...

  4. 【MINA】用mina做业务服之间的通信,实现业务负载均衡思路

    学习mina目的还是搭建通信架构,学完mina我们了解了如何实现客户端和服务端,也就是一个正常channel我们是知道怎么建立的 但是问题是,我们应用环境通信分为两种 1.前后端通信 其实这个比较好实 ...

  5. c#中字符串显示上标和下标解决办法

    由于工作的需求,需要在word中插入带入带有上标和下标的字符串,比如这样的一个字符串:SO₄²⁻(mg/L).在网上搜了好久,终是摸索出点思路. 解决办法:使用转义字符加Unicode的HexEnti ...

  6. Android richtext

    在项目开发过程中经常会遇到很多需要显示不同样式的,不同风格的文本信息:对此可以使用多个TextView来分别设置自已想要的样式以满足需求,但是使用多个TextView的方式不太好:使用多个TextVi ...

  7. 【HTTPS】Https和SSL学习笔记(二)

    此文讲述证书的相关信息,参考文章链接http://www.guokr.com/post/116169/ 一. 证书的类型 常用的几种证书如下: (1) SSL证书,用于加密HTTP (2) 代码签名证 ...

  8. ios简单数据库运用

    一.添加类 二.打开数据库 三.创表 四.插入数据 五.取出数据 一.添加类 1.在设置Linked Frameworks and Libraries 中,点加号并添加libsqlite3.0.dyl ...

  9. ios专题 - objc runtime 动态增加属性

    objective-c中,有类别可以在不修改源码的基础上增加方法:近排在看别人的开源代码时,发现还可以动态增加属性.而且是在运行时,太牛B了. 使用运行时库,必须要先引入 objc/runtime.h ...

  10. 修改虚机IP

    同网段的话,直接修改,不同网段的话,使用以下方法: 步骤一:nova list --all-tenant 找到相应虚拟机+--------------------------------------+ ...