欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

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

发布时间:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的这篇文章主要介绍了 使用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

解释如下:

  • target: 指定输出组件的类型,有DLL/EXE/WINEXE; (如果是EXE,则程序在执行的时候将出现一个DOS窗口(即使是WINFORM的程序). 因此应该设置target为winexe)
  • targetplatform: 输出组件的.net运行版本;
  • 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的代码:

    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,也可以使用(我试过的)。

    总结

    以上是生活随笔为你收集整理的使用ilmerge实现.net程序静态链接的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。