有没有理由为什么DLL重定向除了清单的存在之外不起作用?

时间:2010-08-03 19:39:26

标签: windows windows-7 dll

4 个答案:

答案 0 :(得分:2)

我的第一个想法:.manifest文件及其所有暗示在2002/2003年被添加到Windows XP中。 为什么@#$%会使您的应用 - 以及您的应用所使用的库 - 不使用此技术来解决这个小小的“dll-hell”。 完全是他们开发解决的方案。

接下来,我非常确定“KnownDlls”仅涵盖操作系统在System32中实际发现的dll。在随机路径位置(如Office2002文件夹中)查找dll,我希望至少会失败一些内部健全性检查(is-the-dll-a-real-KnownDlls-candidate)测试。并且在系统文件夹之后搜索PATH,所以当在... \ Office10 \中找到usp10.dll时 - 它不可能是一个真正已知的dll(根据定义)。

接下来,我也确定.local文件没有按照您的想法进行操作。 .local文件的文档完全没有任何意义,因为它真正说的是,.local文件应用后dll的搜索顺序,正是dll的默认搜索顺序 - 在系统文件夹之前始终搜索exe文件夹反正。

唯一一次.local实际上产生的潜在差异是当应用程序使用显式路径在对loadLibrary的调用中加载dll(或使用更改的搜索路径标志到LoadLibrary或使用SetDllSearchDirectory API)时。执行加载的exe或dll的所有情况都是选择一个非常具体的dll - 应用程序作者想要以某种方式覆盖它。 .local文件不能(无论如何看似我)更改任何仅由其名称指定的dll文件的搜索行为。

因此,如果将usp10.dll安装到system32中,它可能会被选为KnownDll然后使用 - 尽管你的本地副本(和.local文件)。 如果它在路径上的其他位置,则应首先使用exe文件夹中的副本 - (假设LoadLibrary(“usp10.dll”)是加载dll的方式)。

即使你付出了所有的努力来创建一个程序集来包含你已知良好的usp10.dll,然后让你的应用程序依赖于它,我仍然认为传递给LoadLibrary的完全限定路径将打败任何搜索逻辑完全 - 包括在依赖程序集列表中查找dll。

所以,你的问题让我困惑。使用的usp10.dll应为

  • system32中的那个(如果存在)(因为KnownDlls覆盖了exe文件夹中的那个)
  • 您的应用程序文件夹中的那个,因为如果KnownDlls未命中,搜索逻辑将始终首先找到这个。

除非usp10.dll实际上是一个com dll,或者在注册表中有一个完全限定的路径,消费者用它来加载它,在这种情况下加载的应该是:

  • 应用程序文件夹中的那个,因为这似乎是.local文件可能适用的一种情况。

鉴于在KnownDLL中存在DLL会抑制.local的功能,并且假设Crystal报告dll是pathalogical ......

我所能建议的是:

该线程包含一个名为PatchIAT的函数 - 将其导入您的代码。

在使用Crystal Reports dll中的任何功能之前(导致他们去寻找usp10.dll) - 调用LoadLibrary来获取dll的句柄,然后在句柄上调用PatchIAT,将dll的调用重定向到LoadLibrary EXE实现的功能。

在EXE LoadLibraryThunk过程中,传递对系统的LoadLibrary的任何调用,除非它对于usp10.dll的显式路径 - 在这些调用上 - 返回错误代码。

Disable antialiasing for a specific GDI device context

答案 1 :(得分:1)

解决方案实际上非常简单,但我花了一段时间才弄明白它的工作原理。

在客户计算机上,我将 usp10.dll从 C:\Windows\System32(已知良好版本)复制到文件夹C:\Program Files\Common Files\Business Objects\3.0\bin(大多数Crystal组件都在其中)安装)。然后我运行了crdeploy.reg文件夹中已存在的bin文件:此文件向注册表添加了HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports密钥,并将值CommonFiles设置为{{1} }}

由于我今天早些时候无法连接到客户的计算机,因此我在Windows 7虚拟机上对该问题进行了更多测试。就像我在其中一个编辑中提到的那样,在这台计算机上,Crystal Reports从未在C:\Program Files\Common Files\Business Objects\3.0\bin目录中查找 usp10.dll ,因此会立即尝试在{{1}中加载副本文件夹。

事实证明,当Crystal Reports调用C:\Program Files\Common Files\Business Objects\3.0\bin时,它会检查以下文件夹中的 usp10.dll

  • 如果注册表中存在C:\Program Files\Common Files\Microsoft Shared\Office10,则会使用该路径调用LoadLibrary

  • 如果该注册表项不存在,或该文件夹中不存在 usp10.dll ,Crystal Reports将使用HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports\CommonFiles作为LoadLibrary来调用LoadLibrary路径。

  • 如果在C:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll文件夹中找不到该文件,它只会将文件名(Office10)传递给usp10.dll,然后会导致Windows加载副本LoadLibrary

因此,在我的测试Windows 7计算机上,我没有设置System32注册表项,因此Crystal Reports始终加载{strong> usp10.dll 的版本{1}}文件夹,即使在CommonFiles中放入 usp10.dll 的副本后也是如此。一旦我将注册表项设置为指向正确的位置,Crystal Reports就会加载正确的文件版本。

在客户的计算机上,注册表已将Office10路径设置为正确的文件夹,但我们的应用程序的安装程序未将 usp10.dll 安装到该文件夹​​,因此它仍然在C:\Program Files\Common Files\Business Objects\3.0\bin文件夹中提取副本。

给客户的最终解决方法非常简单:

  1. usp10.dll 的版本从CommonFiles复制到Office10

  2. 运行System32文件夹中的C:\Program Files\Common Files\Business Objects\3.0\bin文件,以确保crdeploy.reg注册表项存在且指向bin

  3. 我原本以为将 usp10.dll 的副本放到CommonFiles文件夹中会解决客户机器上的问题,但就像我说的那样,这对我来说不起作用Windows 7测试机因为我错过了C:\Program Files\Common Files\Business Objects\3.0\bin注册表项,所以我犹豫是否考虑已发布的修复版。

    此外,如果它帮助其他人遇到此问题,则涉及的 usp10.dll 版本为:

    • 1.405.2416.1:这是bin文件夹中的版本,也是导致Crystal Reports崩溃的版本。当您打印报表时,Crystal Reports调用 usp10.dll 中的一个函数时会发生访问冲突(我没有原始堆栈跟踪,但我认为它是CommonFiles功能)。

    • 1.626.7600.16385:这是一个适用于Crystal Reports的已知良好版本。此版本似乎是默认安装在Windows 7中的版本。

    还有其他版本,例如Windows XP中Office10文件夹中默认安装的版本,也适用于Crystal Reports。

答案 2 :(得分:1)

我在运行Server 2008 R2的TS上遇到了类似的问题。事件日志出错:

Log Name: Application
Source: Application Error
Date: 5/23/2012 10:32:37 AM
Event ID: 1000
Task Category: (100)
Level: Error
Keywords: Classic
User: N/A
Computer: 
Description:
Faulting application name: crw32.exe, version: 11.0.0.1282, time stamp: 0x422d5c77
Faulting module name: usp10.dll, version: 1.420.2600.5969, time stamp: 0x4bc88269
Exception code: 0xc0000005
Fault offset: 0x00014ee4
Faulting process id: 0x1744
Faulting application start time: 0x01cd38f8ce57fbd5
Faulting application path: C:\Program Files (x86)\Business Objects\Crystal Reports 11\crw32.exe
Faulting module path: C:\Program Files (x86)\Common Files\Microsoft Shared\Office10\usp10.dll

我尝试将usp10.dll从\ Windows \ System32复制到C:\ Program Files(x86)\ Common Files \ Business Objects \ 3.0 \ bin。然后运行crdeploy.reg文件,但由于服务器上的64位操作系统,必须手动更新regkey以包含(x86)。 Crystal Reports应用程序仍然无法识别DLL,它一直在查看\ Office10文件夹。所以我只是重命名该文件夹中的DLL副本,然后再次从\ System32复制。这就像一个魅力,DLL上的文件版本与Mike Spross发布的完全相同。

答案 3 :(得分:0)

对于我来说,拥有Windows不知道的额外副本似乎不是一个好主意(如何更新?)

为什么你不能自己打电话给LoadLibrary("usp10.dll")作为你在创业时做的第一件事?