使用ilmerge实现.net程序静态链接

当编写规模稍大一点的程序时,需要进行模块划分。我们一般是对每个模块建一个工程,输出一个类库,这样就形成了一个exe加多个类库的解放方案。这样本身是没有什么问题的,就是发布上稍微有点麻烦,需要发布一个exe加多个dll文件。特别是那些需要经常更新的程序,其实本身可能并不大,一共也就几百kb,但每次还要发布三四个dll确实令人厌烦,做成安装包就更没必要了。

在C++中,我们一般可以通过静态链接解决这种问题,但在.net中却不行,每个类库只能输出dll,VisualStudio官方也没有提供静态链接的选项,其实从理论上讲要想合并似乎也不难,ildasm能够把.NET程序反编译成il,那么把两个il合并到一个il当中再用il编译就可以了。虽然M$却没有直接提供这种功能,但M$的一位大牛提供了一个工具ILMerge可以实现这种功能,可以在http://research.microsoft.com/~mbarnett/ILMerge.aspx下载。

网上也有一些文章对这个工具进行了介绍,margiex的blog中的说明就介绍的较简明扼要,这里转录一下:

ilmerge /ndebug /target:exe /targetplatform:v1.1 /out:newclient.exe oldclient.exe /log AutoUpdater.dll DockingSuite.dll DocumentManager.dll FileHelpers.dll OutlookBar.dll SandBar.dll ICSharpCode.SharpZipLib.dll

解释如下:

  1. target: 指定输出组件的类型,有DLL/EXE/WINEXE; (如果是EXE,则程序在执行的时候将出现一个DOS窗口(即使是WINFORM的程序). 因此应该设置target为winexe)
  2. targetplatform: 输出组件的.net运行版本;
  3. out: 合并后的组件全名;
    后面是主要的被合并的组件名称, 及相关所有的其它DLL;
    上面的示例只是合并为EXE, 也可以多个DLL合并成一个DLL使用, 各自的命名空间不会改变;
  • 不能合并interop这种由COM转换过来的DLL; (可以合并,但相关依赖的DLL必须也一起合并, 第一次合并的时候只有Excel.dll,总是报错,以为是interop的缘故,后来才发现是没有合并vbide.dll的缘故,复制到目录再一起合并,一切OK.)
  • 如果有资源DLL, 应该将要被合并的oldclient.exe先改为别的名称,然后合并后的输出命名为:oldclient.exe,因为资源文件名是:oldclient.resources.dll,而ILMERGE不能合并资源文件,否则在导出后将找不到此资源文件。(如果哪位知道如何合并资源文件,请指教,谢谢)
  • 虽然合并后的EXE比较大,但在用户那里只有一个EXE,这样直观的多,也容易升级维护.

原文地址:http://www.cnblogs.com/margiex/archive/2008/06/24/302329.html

具体的详细使用文档请参看它的说明文档,还是很简单的。

另外,也可以通过编程的方式来调用ILMerge的库来实现简化合并,这里转录一下CodeProject上的一篇文章Post build step static linking tool for C#, using ILMerge的代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Text;
using System.Collections;


namespace HTMerge
{
    
class Program
    {   
        
static void Main(string[] args)
        {
            
try
            {
                String strDir 
= "";
                
if (args.Length != 1)
                {
                    Console.WriteLine(
"Usage: HTMerge directoryName");
                    
return;
                }
                
else
                {
                    strDir 
= args[0];
                }

                String[] exeFiles 
= System.IO.Directory.GetFiles(strDir, "*.exe");
                String[] dllFiles 
= System.IO.Directory.GetFiles(strDir, "*.dll");

                ArrayList ar 
= new ArrayList();

                Boolean bAdded 
= false;

                
//there might be more than 1 exe file, 
                
//we go for the first one that isn't the vshost exe
                foreach (String strExe in exeFiles)
                {
                    
if (!strExe.Contains("vshost"))
                    {
                        ar.Add(strExe);
                        bAdded 
= true;
                        
break;
                    }
                }

                
if (!bAdded)
                {
                    Console.WriteLine(
"Error: No exe could be found");
                    
//I know multiple returns are bad�
                    return;
                }

                bAdded 
= false;

                
foreach (String strDLL in dllFiles)
                {
                    ar.Add(strDLL);
                    bAdded 
= true;
                }

                
//no point merging if nothing to merge with!
                if (!bAdded)
                {
                    Console.WriteLine(
"Error: No DLLs could be found");
                    
//I know multiple returns are bad�
                    return;
                }


                
//You will need to add a reference to ILMerge.exe from Microsoft
                
//See http://research.microsoft.com/~mbarnett/ILMerge.aspx
                ILMerging.ILMerge myMerge = new ILMerging.ILMerge();

                String[] files 
= (String[])ar.ToArray(typeof(string));

                String strTargetDir 
= strDir + "\\Merged";

                
try
                {
                    System.IO.Directory.CreateDirectory(strTargetDir);
                }
                
catch
                {
                }

                
//Here we get the first file name 
                
//(which was the .exe file) and use that
                
// as the output
                String strOutputFile = System.IO.Path.GetFileName(files[0]);

                myMerge.OutputFile 
= strTargetDir + "\\" + strOutputFile;
                myMerge.SetInputAssemblies(files);

                myMerge.Merge();
            }
            
catch (Exception ex)
            {
                Console.WriteLine(String.Format(
"Error :{0}",ex.Message));
            }

        }
    }
}

另外,需要说明的是,这个工具目前支持的是.net 2.0,那些.net 3.0 3.5的程序由于是和.net2.0同一个clr,也可以使用(我试过的)。

转载于:https://www.cnblogs.com/TianFang/archive/2009/10/22/1588320.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值