为什么我在 Vista 上可能会遇到 DLL 未找到异常,但在 XP 上却不会?
我有一个依赖于多个托管库的应用程序。这些托管库又依赖于一些非托管库。
当我将应用程序部署到运行 XP 的计算机时,它运行良好。当我在运行 Vista 的计算机上执行相同操作时,我收到 DLL 未找到异常。
我尝试了 VS2010 安装项目和 NSIS 安装程序来进行部署,这两种情况都是相同的。
为什么会发生这种情况?我能做些什么来绕过它?
更新 - 更多详细信息
- 两个安装程序都会检查 .NET 4.0 的安装,并在需要时安装
- Vista 计算机是 64 位,但安装会按预期定向到 x86 程序文件文件夹
- 在这两种情况下,我都有一个管理员帐户
- DLL与可执行文件保存在同一目录中
- 据我所知,文件被复制到正确的目录
更新 2
- 完整错误位于 http://pastebin.ca/2046487
- 该DLL是Audiere.Net.dll,它是我的一个,是一个托管库。
我不确定该错误是否意味着它找不到 Audiere.Net.dll,或者是否因为找不到它的依赖项之一而无法加载它。
更新 3 - 来自进程监视器的内容
运行进程监视器后(感谢 Mehrdad!),有几个条目的状态不是“成功”。其中一些是“NAME NOT FOUND”,有些是“PATH NOT FOUND”。 (它甚至查询 PDB 文件,我原以为这些文件仅由调试器使用。)很难看出哪些条目可能是导致实际失败的条目。不管怎样,我已经上传了log(过滤以具有相关路径)以防它对任何人都有意义。
更新 4 - 添加了 .pdb 文件
所以我有点绝望,并将 .pdb 文件包含到安装程序的输出中。我以为这没什么用,但实际上却导致了一个更有用的错误。我现在得到一个 BadImageFormatException,而不是简单地说找不到 DLL。谷歌搜索告诉我,这是在 x86 上编译但在 x64 上运行的二进制文件的常见问题(就像 Vista 机器一样)。
建议的补救措施是强制它以 x86 为目标,但 Audiere.Net.dll 已经是这样了。问题可能出在它所包装的库上吗?
I have an app that relies on several managed libraries. These managed libraries in turn rely on some unmanaged libraries.
When I deploy the app to a machine running XP, it runs fine. When I do the same on a machine running Vista, I get a DLL not found exception.
I've tried both a VS2010 setup project and an NSIS installer to do the deployment and it's the same in both cases.
Why might this happen? What can I do to get around it?
Update - Further details
- Both installers check for the installation of .NET 4.0 and install it if need be
- The Vista computer is 64 bit, but the installation gets directed to the x86 program files folder as expected
- In both cases I have an admin account
- The DLLs are kept in the same directory as the executable
- As far as I can tell, the files are getting copied to the right directory
Update 2
- The full error is at http://pastebin.ca/2046487
- The DLL is Audiere.Net.dll, which is one of mine and is a managed library.
I'm not sure if that error means that it can't find Audiere.Net.dll, or whether it can't load it because one of it's dependencies can't be found.
Update 3 - Stuff from Process Monitor
After running process monitor (thanks Mehrdad!) there are several entries which don't have a status of "SUCCESS". Some of these are "NAME NOT FOUND" and some are "PATH NOT FOUND". (It's even querying the PDB files, which I had thought were only used by a debugger.) It's really hard to see which entries might be the one leading to the actual failure. Anyway, I've uploaded the log (filtered to have a relevant path) in case it means something to anyone.
Update 4 - Added .pdb files
So I kinda got desperate and included the .pdb files to the output of the installer. I thought it would be useless, but it actually resulted in a more useful error. Rather than simply saying DLL not found, I now get a BadImageFormatException. Googling this tells me that this is a common problem for binaries compiled on x86 but being run on x64 (as the Vista machine is).
The suggested remedy is to force it to target x86, but Audiere.Net.dll already was. Could the fault lie with the library that it wraps?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
也许存在某种重定向实际上并没有让您的应用程序安装在预期的文件夹中?
我们需要更多细节,但是您是为用户安装还是为机器安装?您是管理员吗? DLL通常位于哪里?
编辑:尝试使用进程监视器来监视什么文件实际上正在被访问。
Maybe there's some sort of redirection that's not actually letting your app install in the intended folder?
We'd need a bit more detail, but are you installing for the user or the machine? Are you an admin? Where is the DLL normally located?
Edit: Try using Process Monitor to monitor what file is actually being accessed.
如果您正在运行 .Net 应用程序,两台计算机是否都安装了正确的框架?
If you are running a .Net application, do both computers have the proper Framework installed?
您提到 Audiere.Net.dll 是针对 x86 的,但是您的可执行文件呢?
显然,您可以重新编译您的程序或使用 Corflags(框架的一部分)来查看 exe 上的当前设置。
或者设置或取消设置标志
(注意,如果您的应用程序使用强名称签名,则除非您使用 /Force 删除签名,否则它将无法工作)
You mention that Audiere.Net.dll is targeted at x86, but what about your executable?
You can obviously recompile your program or use Corflags (part of the framework) to view the current setting on your exe.
Or to set or unset the flag
(Note, if your app is signed with a strong name it won't work unless you use /Force to remove the signature)
解决方案非常简单:需要针对 x64 重新编译非托管 DLL 之一。
关键步骤:
BadImageFormatException
)具体情况:
Audiere.Net.dll
引起的,但实际上是由libaudieresharpglue.dll
的问题引起的。The solution turned out to be quite straightforward: one of the unmanaged DLLs needed to be recompiled for x64.
Key steps:
BadImageFormatException
)Specifics:
Audiere.Net.dll
, but was actually caused by a problem withlibaudieresharpglue.dll
.通常的原因是,有问题的 dll 依赖于 Vista 计算机上不存在的其他 dll(或者可能存在但未注册)。
Usual reason is that the dll in question depends on other dlls which are not on the Vista machine (or possibly there but not registered.)
我们遇到了类似的情况,发现我们需要下载 c++ Redistibuatable Package 使程序能够使用第 3 方 dll 在 Windows 7 上运行。
We ran into something simlar and found we needed to download the c++ Redistibuatable Package to get the program to run on windows 7 using 3rd party dlls.
我记得在使用 SQLite 包装器时遇到过类似的问题。
当然,问题的根源是 32/64 位问题,这与 SQLite 包装器是托管包装器的情况相同,这使得它依赖于处理器。
我猜测,虽然您的托管库 (Audiere.Net.dll) 是为 32 位编译的,但您的主应用程序 (ssd2.exe) 却不是。
安装文件夹由安装程序的配置决定,但如果应用程序项目未严格配置为编译为 x86 项目(通常针对默认的 Any Cpu 环境),则应用程序将作为64 位进程,无论安装路径如何。这可以通过查看 64 位计算机上的任务管理器中的进程来轻松验证,所有 32 位进程在 64 位 Windows 计算机上都有一个额外的 *32 (它们在 32 位计算机上不会有它)。
编辑:或更容易地通过查看项目属性 - >构建 - >平台目标 :)
无论如何 - 您应该将构建 ssd2.exe 的项目的项目设置更改为目标 x86,应该没问题。
I recall running into a similar issue with SQLite wrapper.
The source of the problem is the 32/64 bit issue of course, and it's the same scenario as the SQLite wrapper is a managed wrapper which makes it processor dependent.
I am guessing that while you're managed lib (Audiere.Net.dll) is compiled for 32 bits, you main application (ssd2.exe) is not.
The installation folder is determined by the configuration of the setup, but if the application project is not strictly configured to compile as a x86 project (usually targeting the default Any Cpu environment) then the application will launch as a 64 bit process, regardless of the installation path. This can be easily verified by looking at the process in task manager on a 64 bit machine, all 32 bit processes have an additional *32 on a 64 bit windows machine (they won't have it on a 32 bit machine).
EDIT: or more easily by looking at the project properties->Build-> Platform Target :)
Anyhow - you should change the project settings for the project that builds ssd2.exe to target x86 and you should be ok.