【已解决】C#中集成DLL库到自己的exe程序中

【问题】

已经实现了下载ST歌曲的小程序,但是由于其中注册快捷键的功能,需要调用额外的一个dll库,Interop.SHDocVw.dll,所以发布的时候,除了发布一个单独的exe之外,还需要连带dll一起发布,很是不爽。

希望将此dll集成到exe中。

【解决过程】

1.从:

如何实现将dll文件集成到exe中

找到:

C# 调用 ilmerge 合并Dll

C#中用ILMerge将所有引用的DLL和exe文件打成一个exe文件

但是个人觉得还是很麻烦,暂且不去使用这类方法,再去找找是否有更好的办法。

2.后来参考:

C#中怎样让引用的.dll文件也集成到生成的.exe文件中

但是去找了下,所引用的dll是Interop.SHDocVw,但是其属性中,找不到其所说的“嵌入互操作类型”:

找不到 嵌入互操作类型

3.再参考:

VS2010中,无法嵌入互操作类型“……”,请改用适用的接口的解决方法

重新去添加此dll,看看是否可以设置。

但是此处却找不到Interop.SHDocVw.dll是在哪里引用的了。

然后去代码中看了看,相关代码是:

SHDocVw.ShellWindows sws = new SHDocVw.ShellWindows();

然后后来手动删除该SHDocVw,然后尝试查找。

后来折腾了半天,终于找到了。

本来是知道了该dll是属于Microsoft Internet Controls的,所以后来尝试找此关键字,最后是在COM中找到了:

找到了Microsoft Internet Controls的ieframe

添加了后,就可以看到那个SHDocVw了。

4.后来又参考了:

COM Interop, isolation and excluding duplicate references

了解到了,对于SHDocVw的属性中的Isolated,如果设置为True,则说明当编译此项目的时候,不拷贝此dll到程序所在目录。

而此处,看起来,本身就是操作系统自带的此功能的支持,所以也不需要拷贝了。

所以暂时把其设置为True:

Isolated true

然后重新编译试试,结果出错:

------ Rebuild All started: Project: downloadSongtasteMusic, Configuration: Debug x86 ------
Build started 9/25/2012 2:43:08 PM.
CoreClean:
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.exe.config".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.exe".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.pdb".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\Interop.SHDocVw.dll".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\Interop.SHDocVw.dll".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.csproj.ResolveComReference.cache".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.completeHint.resources".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.frmDownloadSongtasteMusic.resources".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.Properties.Resources.resources".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\ResGen.read.1.tlog".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\ResGen.write.1.tlog".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.exe".
  Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.pdb".
ResolveComReferences:
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\TlbImp.exe C:\Windows\SysWOW64\ieframe.dll /namespace:SHDocVw /machine:X86 /out:obj\x86\Debug\Interop.SHDocVw.dll /sysarray /transform:DispRet /reference:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Common\Microsoft.mshtml.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Deployment.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:C:\Windows\assembly\GAC\stdole\7.0.3300.0__b03f5f7f11d50a3a\stdole.dll 
CoreResGen:
  C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\x64\Tracker.exe @"C:\Users\CLi\AppData\Local\Temp\bdd23727ee984f33b6ad9449e552f963.tmp"  /c "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\ResGen.exe" /useSourcePath /r:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Common\Microsoft.mshtml.dll" /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Deployment.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll /r:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /r:obj\x86\Debug\Interop.SHDocVw.dll /compile completeHint.resx,obj\x86\Debug\downloadSongtasteMusic.completeHint.resources frmDownloadSongtasteMusic.resx,obj\x86\Debug\downloadSongtasteMusic.frmDownloadSongtasteMusic.resources Properties\Resources.resx,obj\x86\Debug\downloadSongtasteMusic.Properties.Resources.resources 
CoreCompile:
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /platform:x86 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Visual Studio Tools for Office\PIA\Common\Microsoft.mshtml.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Deployment.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:obj\x86\Debug\Interop.SHDocVw.dll /debug+ /debug:full /filealign:512 /nowin32manifest /optimize- /out:obj\x86\Debug\downloadSongtasteMusic.exe /resource:obj\x86\Debug\downloadSongtasteMusic.completeHint.resources /resource:obj\x86\Debug\downloadSongtasteMusic.frmDownloadSongtasteMusic.resources /resource:obj\x86\Debug\downloadSongtasteMusic.Properties.Resources.resources /target:winexe /win32icon:songtaste_32x32.ico completeHint.cs completeHint.Designer.cs crifanLib.cs downloadStMusic.cs frmDownloadSongtasteMusic.cs frmDownloadSongtasteMusic.Designer.cs Program.cs Properties\AssemblyInfo.cs Properties\Resources.Designer.cs Properties\Settings.Designer.cs
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Components under system file protection should not be isolated.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{eab22ac3-30c1-11cf-a7eb-0000c05bae0b}\MiscStatus' was not imported.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{8856f961-340a-11d0-a96b-00c04fd705a2}\MiscStatus' was not imported.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Out of process servers are not supported
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): error MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{0002df01-0000-0000-c000-000000000046}\InProcServer32' is missing value '(Default)'.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Out of process servers are not supported
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): error MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{d5e8041d-920f-45e9-b8fb-b1deb82c6e5e}\InProcServer32' is missing value '(Default)'.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): error MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{9ba05972-f6a8-11cf-a442-00a0c90a8f39}\InProcServer32' is missing value '(Default)'.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2580,9): warning MSB3179: Problem isolating COM reference 'SHDocVw': Registry key 'HKEY_CLASSES_ROOT\CLSID\{55136805-b2de-11d1-b9f2-00a0c98bc547}\MiscStatus' was not imported.
 
Build FAILED.
 
Time Elapsed 00:00:01.84
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

然后看了下,再去把Copy Local设置为False,试试,结果还是编译出错。

所以,还是改回去,

Isolated为False

就可以正常编译了,

而Copy Local可以为False的。

5.参考:

Embedding DLLs in a compiled executable

去添加dll到resource中:

add existing file

add shdocvw dll

added Interop_SHDocVw

然后再去设置为 embedded resource:

embedded resource

然后参考:

Embed managed dlls easily in a .NET assembly

的代码,添加代码为:

namespace downloadSongtasteMusic
{
    class songtaste
    {
...
        public songtaste()
        {
            crl = new crifanLib();
 
            AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        }
 
        System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
  
            dllName = dllName.Replace(".", "_");
  
            if (dllName.EndsWith("_resources")) return null;
  
            System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
  
            byte[] bytes = (byte[])rm.GetObject(dllName);
  
            return System.Reflection.Assembly.Load(bytes);
        }

如此,也不知道是否可以。

【总结】

等待以后确认,暂时不知道是否可行。

因为之前试过了,即使把downloadSongtasteMusic.exe同文件夹下的Interop.SHDocVw.dll删除掉,也还是可以运行的,所以此处无法测试。

等以后有空换个电脑测试测试此法是否可用。


【后记 1】

后来对于上述方法集成的exe,拿到别的另外一台同样配置和系统的机子上测试,是可以运行的。

但是猜测还是由于同样是64位win7,所以肯定是可以运行的。

还需要找找其他不同系统,比如xp,去测试,才可以确定上述方法的真正可行性。

另外,上述方法,还是有点问题,因为先后出现了:

【已解决】C#项目编译出错:TlbImp : error TI0000: System.UnauthorizedAccessException – Access to the path xxx is denied. Microsoft.Common.targets: warning MSB3283: Cannot find wrapper assembly for type library "SHDocVw".

【已解决】C#项目Clean出错:Error 1 Resource ‘Interop_SHDocVw’ could not be loaded because the file to which it is linked could not be found


【后记 2】

最后,还是通过自己另一番的折腾,感觉新方法,会更好些:

【已解决】C#项目Clean出错:Error 1 Resource ‘Interop_SHDocVw’ could not be loaded because the file to which it is linked could not be found

中的方法类似,把相关的dll文件Interop.SHDocVw.dll,拷贝到单独的位置,然后再去添加引用此dll:

add reference

selecte res dir dll

然后添加后,SHDocVw的错误消失了,就可以正常编译了,:

added dll then SHDocVw compile ok

此时,就可以:

  • 删除之前作为资源所添加的Interop.SHDocVw.dll:

    • remove dll in resources

  • 也可以把之前的System.Reflection.Assembly相关的代码去掉了:

    • remove reflection code

如此做法,目前至少编译上是OK的,而实际上,应该也是可以正常运行的。

即实现了将dll集成到exe中了。

不过还是需要等待以后的测试才知道最终结果。

后来,经过验证,此法是行不通的,具体折腾过程参见:

【已解决】C#编译出来的程序运行出错:Unhandled exception has occurred in your application。System.IO.FileNotFoundException: Could not load file or assembly xxx or one of its dependencies. The system cannot find the file specified.

所以,还是需要换之前的方法。

最后,经过测试,还是原先的那个方法,可以实现集成dll到exe中:


【整理】C#中集成dll到exe中的方法

【最新整理: 2013-04-11】

把dll文件添加为资源文件

项目属性->Resources->Add Resource->Add Existing File:

add existing file 2

然后注意设置过滤规则为 *.*,才能显示出来dll文件,然后把dll添加进来:

select dll file

把dll文件添加到项目中

【此步骤可选】右击项目->添加->新建文件夹:

right click project add new folder

再导入对应的dll文件:

add existing dll

然后选择对应dll,导入即可。

设置项目中的DLL文件为“嵌入的资源”

然后,在左边的项目列表中,点击对应的dll文件,右键选择属性,设置“生成操作”为“嵌入的资源”:

the dll property

其中,如果是英文环境,对应的是把"Build Action"设置为"Embedded Resource"

set to embedded resource

表示,此项目会把此dll集成到生成的(exe)文件中,以此实现dll先集成到生成的exe文件本身中。

通过Reflection代码实现载入内置的(dll)资源文件

把下面代码,添加到你的项目的主类中:

...
 
namespace downloadSongtasteMusic
{
    class songtaste
    {
...
        public songtaste()
        {
            ...
 
            AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        }
 
        System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
 
            dllName = dllName.Replace(".", "_");
 
            if (dllName.EndsWith("_resources")) return null;
 
            System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
 
            byte[] bytes = (byte[])rm.GetObject(dllName);
 
            return System.Reflection.Assembly.Load(bytes);
        }
         
        ...
    }
}

如此,其会在主程序初始化的时候,就去把内在的那些资源文件,此处包括你所添加的dll文件,载入尽量,实现了载入dll库文件(相关的函数)的目的。

因此,你的程序调用dll中的函数,也才能找到合适的函数,而不会出现找不到函数,找不到dll库的问题。

 

至此,就实现了,C#中将dll集成到exe中的目的了。

注意事项:

1.把dll添加作为资源文件,之前以为是可以省略的呢,后来证实,这一步是必不可少的。否则,也是无法把dll集成进来的。

2. 对于上述,在类初始化函数中的,要添加的那句:

AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);

千万不能忘了!!!

否则就像我此处,调试了半天,最终也没有实现对应的集成dll到exe的效果。

最后是找到此处忘了添加这句,导致没有集成dll成功。

所以,千万不要犯和我此处同样的错误。

3.只是把dll导入为资源(res)文件后,在项目文件列表中,是看不到对应的文件的;

只能是,另外再导入现存的dll文件,才能在项目文件列表中,看到对应的dll,才能选择该dll,设置为嵌入的资源;

4.不同的类,比如一个winForm类frmFiverrComScraper.cs,另外一个我自己的库crifanLib.cs,

如果使用到了对应的dll(中的类),那么,分别都要在自己的类的构造函数中,加入对应的

AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {…..}

部分的代码的。

当然,多个类,可以通用一份CurrentDomain_AssemblyResolve的代码实现。

5.如果exe是在网上邻居/网络共享中运行的话,可能会出现问题,详情参考:

【已解决】C#编译出来的程序运行出错:System.Configuration.ConfigurationErrorsException: Error creating the Web Proxy specified in the ‘system.new/defaultProxy’ configuration section.

但是如果是本地,即当前电脑的硬盘上运行,则不会出现这类问题的。



5 Thoughts on “【已解决】C#中集成DLL库到自己的exe程序中

  1. 博主真牛,这么耐心,佩服

  2. 感谢博主的折腾精神,
    在vs08下没法用嵌入资源的方式,可直接在项目上添加现用项,其它参考这篇博文就ok了。http://www.cnblogs.com/kui2/archive/2012/11/29/embedded-dll.html

  3. C#中怎样让引用的.dll文件也集成到生成的.exe文件中

    但是去找了下,所引用的dll是Interop.SHDocVw,但是其属性中,找不到其所说的“嵌入互操作类型”:
    ============

    这个需要.net framework 4.0以上才支持

    • 多谢提醒。
      话说,我之前写程序,也是尽量使用.NET 2.0的,希望尽量保持向后兼容性。
      当然,有机会使用.NET 4.0,也可以利用更多的新特性。算是各有优劣了。

      • 我们现在拿.net做个互联网产品,也是基于2.0框架。其他版本框架太大了。
        忍不住吐槽下微软,你就不能在推出xp sp3 补丁的时候,把.net 框架也打进去?真不知道微软是怎么想的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量