前言
在使用C#调用CLR C++ DLL开发程序完成后在本机上运行正常(本机为Win8.1 64位系统),在将生成的程序复制到客户机电脑上时(Win7 32位操作系统),遇到了如下所示提示:
未能加载文件或程序集“XXXX.dll”或它的某一个依赖项,不是有效的WIN32位应用程序。(异常来自 HRESULT:0x800700C1)
分析
分析XXXX.dll的依赖关系
使用Depends.Exe(Visual Studio工具,该类工具很多可根据使用习惯来选择)分析XXXX.dll中存在的依赖关系,分析后发现存在存在一个MFC和msvcr的DLL是客户上没有的,直接根据名称在硬盘中查找即可知道是否存在,将本机(Win8.1开发机)上C:\Windows\System32下对应dll复制到客户机程序运行目录下,程序依旧崩溃。
网上查询该问题解决方案
基本上都是说X64程序调用了X86的DLL,存在相互调用的问题。但是我开发环境显然配置等都是正确的,不然按道理本机程序就应该无法正常运行,考虑可能是存在编译环境等因素导致异常。
下载eXeScope(PE格式文件查看工具,具体可根据个人喜好进行选择),先后分析exe和dll的中对系统版本的支持信息(操作系统版本支持信息)和运行平台信息(X64还是X86):
程序运行平台信息主要查看Coff Header字段中0x0000011C位置值,该程序和调用DLL中该位置值都为0x014C(I386即32位系统运行程序。)
程序和DLL运行操作系统平台主要查看Optional Header中OS Major Version和OS Minor Version信息,在命令行下直接输入ver即可查看到本机操作系统版本的编号信息。如在我Win8.1操作系统上运行ver,可以看到如下提示信息:Microsoft Windows [版本 6.3.9600]
以上操作证明程序和生成DLL都是32位环境运行并无问题。
怀疑还是DLL依赖上还是存在问题
进入正题,此处才是重点。既然本机能运行那么本机肯定有对应DLL加载信息,调试程序时看到Output下输出如下信息:
'WindowsFormsApplication1.exe': Loaded 'C:\Windows\SysWOW64\mfc110ud.dll', Symbols loaded.
'WindowsFormsApplication1.exe': Loaded 'C:\Windows\SysWOW64\msvcr110d.dll', Symbols loaded.
突然发现自己复制到客户机上的dll位置与Output输出位置信息不一致,然后将SysWOW64中对应DLL替换前面复制过去的dll信息,程序正常运行。原因很简单就是前面复制的DLL是64位系统使用的,32位系统无法识别所以出现了如上所示提示信息。
如果意外碰到类似存在DLL依赖关系都可以通过程序启动时的Output输出信息来将对应DLL复制到新的环境一般应该都可解决问题,如果是应用程序则可以通过依赖关系查看程序复制对应的DLL到新程序目录即可。
扩展阅读
64位系统下SysWOW64文件夹的作用具体见链接:https://en.wikipedia.org/wiki/WoW64