C#中集成DLL库到自己的exe程序中


原文:http://www.crifan.com/csharp_integrate_dll_library_into_exe_application/

已经实现了下载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

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

 1 ------ Rebuild All started: Project: downloadSongtasteMusic, Configuration: Debug x86 ------
 2 Build started 9/25/2012 2:43:08 PM.
 3 CoreClean:
 4   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.exe.config".
 5   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.exe".
 6   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\downloadSongtasteMusic.pdb".
 7   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\bin\Debug\Interop.SHDocVw.dll".
 8   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\Interop.SHDocVw.dll".
 9   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.csproj.ResolveComReference.cache".
10   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.completeHint.resources".
11   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.frmDownloadSongtasteMusic.resources".
12   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.Properties.Resources.resources".
13   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\ResGen.read.1.tlog".
14   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\ResGen.write.1.tlog".
15   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.exe".
16   Deleting file "D:\tmp\tmp_dev_root\downloadSongtasteMusic\downloadSongtasteMusic\downloadSongtasteMusic\obj\x86\Debug\downloadSongtasteMusic.pdb".
17 ResolveComReferences:
18   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 
19 CoreResGen:
20   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 
21 CoreCompile:
22   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
23 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.
24 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.
25 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.
26 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
27 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)'.
28 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
29 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)'.
30 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)'.
31 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.
32   
33 Build FAILED.
34   
35 Time Elapsed 00:00:01.84
36 ========== 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

的代码,添加代码为:

 1 namespace downloadSongtasteMusic
 2 {
 3     class songtaste
 4     {
 5 ...
 6         public songtaste()
 7         {
 8             crl = new crifanLib();
 9   
10             AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
11         }
12   
13         System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
14         {
15             string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
16    
17             dllName = dllName.Replace(".", "_");
18    
19             if (dllName.EndsWith("_resources")) return null;
20    
21             System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
22    
23             byte[] bytes = (byte[])rm.GetObject(dllName);
24    
25             return System.Reflection.Assembly.Load(bytes);
26         }
如此,也不知道是否可以。

【总结】

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

因为之前试过了,即使把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文件为“嵌入的资源”

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

set to embedded resource

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

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

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

 1 ...
 2   
 3 namespace downloadSongtasteMusic
 4 {
 5     class songtaste
 6     {
 7 ...
 8         public songtaste()
 9         {
10             ...
11   
12             AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
13         }
14   
15         System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
16         {
17             string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
18   
19             dllName = dllName.Replace(".", "_");
20   
21             if (dllName.EndsWith("_resources")) return null;
22   
23             System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());
24   
25             byte[] bytes = (byte[])rm.GetObject(dllName);
26   
27             return System.Reflection.Assembly.Load(bytes);
28         }
29           
30         ...
31     }
32 }
如此,其会在主程序初始化的时候,就去把内在的那些资源文件,此处包括你所添加的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.

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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM