【问题】
通过之前的折腾:
已经实现了将dll文件,Interop.SHDocVw.dll,集成到了exe中了。
C#项目编译出来的exe:
1.4版本的 downloadSongtasteMusic.exe
是可以在别的一个x64的win7中正常运行的。
然后又找到了另外一个32位的XP去测试,也是可以正常执行的。
但是,此exe放在当前电脑,另一个x64的win7中,却出错了:
错误文字:
应用程序中发生了无法处理的异常。如果单击“继续”,应用程序将忽略此错误并尝试继续。
如果单击“退出”,应用程序将立即关闭。
未能加载文件或程序集“Microsoft.mshtml,Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b3f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。
错误截图:
【解决过程】
1.以为只是最新我编译出来的1.4版本的有问题呢。
后来发现,原来之前的1.2的版本,也会出现同样的错误:
要知道,本身此旧版本,可是在exe同目录下,已经放了对应的dll文件Interop.SHDocVw.dll了的:
但是很明显,不是Interop.SHDocVw.dll的问题,而是那个mshtml的问题。
2.才想起来,其实之前在本电脑中使用32位的win7时,上面那个1.2版本的exe是可以正常执行的。
说明那时候,是有该mshtml相关的dll的,所以运行时没问题。
此处是64位的win7,缺少相关的那个mshtml,所以才出了问题的。
不过倒是有点奇怪的是,本身上述的exe,就是在另外一台64位win7中用VS2010编译出来的,虽然生成的是obj\x86文件夹下,但是也应该是通用的才对,不该出错才对。
3.等有空参考这个:
未能加载文件或程序集 ‘ Microsoft.mshtml…强名称验证失败。
去试试。
4.后来继续折腾。
参考关于 VS2005 打包 Microsoft.mshtml 的解决方法,去打开Visual Studio Command Prompt:
然后执行:
tlbimp C:\Windows\System32\mshtml.tlb /out:D:\tmp\Microsoft.mshtml.dll
结果出现一堆警告:
不过最后倒是可以执行完毕了:
可以实现导出Microsoft.mshtml.dll,去看了下,有10多M大小。
5. 然后把用tlbimp导出的10多M的Microsoft.mshtml.dll,添加到项目的资源中,并且设置为 嵌入式资源。
然后重新编译出来的exe很大,达到20M(之前只有400K)。
但是结果放到XP中运行,又出错了:
A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
6.所以说明此办法无效,所以回到C#项目中,删除这个,被当做嵌入式资源的,用tlbimp导出的,Microsoft.mshtml.dll。
7. 然后继续折腾。
把原先的项目引用的MSHTML对应的属性中Copy Local为True:
这样,就可以实现,在编译完成后,把相关的所引用的那个
C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll
拷贝到输出目录了。
然后编译一下,却没在项目主路径下的Debug\x86找到所要的Microsoft.mshtml.dll。
然后后来还是通过编译所输出的log中的:
Copying file from "C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll" to "bin\Debug\Microsoft.mshtml.dll".
找到了,是在bin目录下所要的Microsoft.mshtml.dll,只有7M多。
8.然后重新把此dll作为嵌入式资源,重新编译生成的exe,有15M多,放到XP下去运行。
最后终于是消除了此错误,程序可以正常运行了。
【总结】
对于C#项目编译出来的exe,放到别的环境下,比如XP下,运行出错:
未能加载文件或程序集“Microsoft.mshtml,Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b3f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。
的话,解决办法是:
1.想办法先找到程序所引用的那个Microsoft.mshtml.dll
想找到Microsoft.mshtml.dll,有两种办法:
【推荐】方法1:项目引用中的MSHTML的属性中的Copy Local为True:
然后编译项目,然后就可以从程序输出目录中可以找到Microsoft.mshtml.dll了。
注:如果像我开始一样不知道项目输出目录在哪,可以参考编译的log输出,可以找到类似如下的这句:
Copying file from "C:\Windows\assembly\GAC\Microsoft.mshtml\7.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll" to "bin\Debug\Microsoft.mshtml.dll".
很明显,到你项目路径\bin\Debug下,就可以找到Microsoft.mshtml.dll了。
【不推荐】方法2:用tlbimp从C:\Windows\System32\mshtml.tlb导出Microsoft.mshtml.dll
具体做法是:
A。打开VS的命令行:
B。运行命令:
tlbimp C:\Windows\System32\mshtml.tlb /out:D:\tmp\Microsoft.mshtml.dll
即可从C:\Windows\System32\mshtml.tlb导出dll,被导出的dll,被命名为Microsoft.mshtml.dll,放在了D:\tmp下了。
注:之所以不推荐此法,是因为我开始就是用此法,结果导出的Microsoft.mshtml.dll是有问题的dll,无法正常使用的。
不知道是不是由于32位和64位的区别所导致的。
2. 办法让你程序执行时也能找到此Microsoft.mshtml.dll文件(这样程序运行时就不会报错了)
而想办法让程序运行时找到Microsoft.mshtml.dll,也有两种办法:
【推荐】方法1:Microsoft.mshtml.dll放到和当前程序(exe)同目录下
此处主要是涉及到项目发布打包的过程。
将所获得的Microsoft.mshtml.dll,在项目部署过程中,添加进来,项目打包发布时,保证客户安装程序后,Microsoft.mshtml.dll是和你程序(exe)都在同一目录下即可。
具体方法自己网上可以找到一堆,自己不再啰嗦。
注:此法优点是,不需要将Microsoft.mshtml.dll集成到exe中,不会增加exe文件大小。
【不推荐】方法2:将Microsoft.mshtml.dll集成到程序(exe)中
关于把dll集成到exe中的办法,可参考:
注:理论上来说,不推荐此办法,因为会增加exe的大小。
比如我的exe原先是本身只有几百K,集成了另一个dll后,也才1M多,但是再集成了7M多的Microsoft.mshtml.dll,结果最终的exe变成了15M多,太尼玛大了。
而此处,本人之所以采用了此法,是因为不希望发布exe时,还带个独立的dll,不方便exe的使用和传播。
但是缺点就是上面说的,会导致exe太大。
所以,具体采用哪种方案,你自己根据自己的考虑因素,自己取舍。
转载请注明:在路上 » 【已解决】Win7中运行exe出错:应用程序中发生了无法处理的异常。未能加载文件或程序集“Microsoft.mshtml,Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b3f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件