Mik*_*oss 6 windows dll windows-7
我们有一个遗留的VB6应用程序,它使用Crystal Reports XI生成打印报告.我们通过经验发现,如果Crystal Reports打印引擎选择了错误版本的usp10.dll(Windows Uniscribe库),它就会崩溃.
一位客户在其Windows 7计算机上一直存在打印问题(运行Windows 7 Enterprise,32位).但是,我们还有一些其他客户运行各种版本的Windows 7,没有任何问题.
在其中一台出现打印问题的计算机上,我注意到usp10.dll该文件夹中存在旧版本(与Crystal Reports XI不兼容)C:\Program Files\Common Files\Microsoft Shared\Office10\.我不确定是什么应用程序安装了这些文件,因为客户没有安装Office 2002(所以我假设另一个应用程序安装了它们).但是,我暂时重命名了该文件,我们的应用程序能够正确打印,因此我们的应用程序似乎最初正在加载该文件的版本,这导致了崩溃.
崩溃仅在用户尝试打印报告时发生.我们的应用程序直接依赖于craxdrt.dll(Crystal Reports ActiveX Designer运行时库)和crviewer.dll(Crystal ActiveX报表查看器库),无论我们是通过craxdrt.dll还是通过Report Viewer控件直接打印,都会发生崩溃.
过去,我们通过将已知良好版本的usp10.dll复制到我们的应用程序目录并创建.local文件来启用DLL重定向来解决此问题.在客户站点,我尝试了这个,并尝试了为我们的EXE 创建.local文件夹并将usp10.dll放在那里的替代方法,但这两种方法都没有在我连接的机器上运行.
我注意到usp10.dll是Windows中的一个"已知"DLL(它有一个条目HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs),但我在另一台Windows 7机器上运行我的应用程序(运行专业版,32位),这里也列出了DLL注册表中的已知DLL,通过使用Dependency Walker,我可以看到重定向正在该计算机上运行.这有点令人困惑,因为Microsoft 文档声明已知的DLL无法重定向.此外,正如我在问题标题中暗示的那样,我们的主要EXE不使用清单文件(Microsoft文档声明存在清单,嵌入式或独立式,禁用DLL重定向).
所以,我的问题是,有没有其他原因可以解决为什么DLL重定向可以在某些机器而不是其他机器上运行,这是否与Windows 7和Windows XP之间的差异有关?我曾考虑删除KnownDLLs注册表项中的所有内容,但由于重定向工作在此处具有相同设置的计算机上KnownDLLs,我不确定是否会实际解决问题,我不想删除该密钥我不需要.我还没有机会再次连接到客户的机器来运行Dependency Walker,但我不确定我是否能够解释它的日志(即使在它工作的机器上,我看到了很多LoadLibrary调用usp10.dll 指向重定向文件夹以外的文件夹,但有些调用显然已重定向,所以我不确定这意味着什么).
编辑:我应该还提到,每一次我们也已检查计算机具有的另一个副本usp10.dll中System32的文件夹.看着克里斯的回答和这篇博客文章由拉里·奥斯特曼解释如何已知的DLL工作多一点,我意识到,这可能不会纳入到问题都没有,因为我们的程序没有加载的副本usp10.dll是在System32夹.
编辑#2:在我的VB6开发机器(Windows XP SP3)上运行了Dependency Walker之后,打印一直有效,我能够收集到一些信息.我在Dependency Walker中分析了我们的应用程序,并将其设置为记录完整路径名,看起来像Crystal Reports依赖项之一(另一个Crystal Reports DLL)尝试从放弃之前从多个(硬编码)路径加载usp10.dll只是通过文件名来询问它.事实证明,它首先尝试从Crystal Reports bin文件夹加载它,然后尝试从中加载它C:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll.如果它无法在任何一个位置找到它,它只是要求Windows usp10.dll(它会抓住一个)System32).但即便如此也不一致.有时它会询问文件Office10夹中的文件,然后似乎忽略了无法找到文件的事实,而有时则会出现一系列LoadLibrary调用,看起来Crystal Reports代码正在主动查找备用副本在不同位置的文件.更令人困惑的是,至少有一个Crystal Reports组件看起来实际上对usp10.dll具有加载时依赖性,因此该组件似乎总是得到副本System32.
我还没有100%的清楚,为什么在.local重定向不会在该客户的电脑这种情况下工作,但我认为这部分解释了为什么这个特殊的客户遇到的问题,因为所有有问题的计算机上有一个Office10文件夹的显然是不兼容的版本usp10.dll.
但是,我再次提出了一个基本问题:如果这些组件在很多不同的地方寻找这个文件,我怎么能保证他们都会使用同一个副本呢?
该解决方案实际上非常简单,但我花了一段时间才弄清楚它为什么有效。
在客户计算机上,我将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为C:\Program Files\Common Files\Business Objects\3.0\bin.
由于今天早些时候我无法连接到客户的计算机,因此我在 Windows 7 虚拟机上对该问题进行了更多测试。正如我在一次编辑中提到的,在这台计算机上,Crystal Reports 从未在C:\Program Files\Common Files\Business Objects\3.0\bin目录中查找usp10.dll,因此它会立即尝试加载文件C:\Program Files\Common Files\Microsoft Shared\Office10夹中的副本。
事实证明,当 Crystal Reports 调用时LoadLibrary,它会检查以下文件夹中是否有usp10.dll:
如果HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports\CommonFiles注册表中存在,则它会LoadLibrary使用该路径进行调用。
如果注册表项不存在,或者该文件夹中不存在usp10.dllLoadLibrary ,Crystal Reports 将调用withC:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll作为路径。
如果在文件夹中找不到该文件Office10,它只会将文件名 ( usp10.dll) 传递给LoadLibrary,然后 Windows 将副本加载到 中System32。
因此,在我的测试 Windows 7 计算机上,我没有设置注册表项,因此 Crystal Reports 始终加载文件夹中的usp10.dllCommonFiles版本,即使将usp10.dll的副本放入. 一旦我将注册表项设置为指向正确的位置,Crystal Reports 就会加载该文件的正确版本。Office10C:\Program Files\Common Files\Business Objects\3.0\bin
在客户的计算机上,注册表已将路径CommonFiles设置为正确的文件夹,但我们应用程序的安装程序并未将usp10.dll安装到该文件夹,因此它仍在获取该Office10文件夹中的副本。
给客户的最终解决方法非常简单:
将usp10.dll的版本从System32复制到C:\Program Files\Common Files\Business Objects\3.0\bin。
运行文件夹crdeploy.reg中的文件bin以确保CommonFiles注册表项存在并且指向C:\Program Files\Common Files\Business Objects\3.0\bin.
我原本以为将usp10.dll的副本放入该bin文件夹中可以解决客户计算机上的问题,但正如我所说,这在我的 Windows 7 测试计算机上不起作用,因为我缺少注册表CommonFiles项,所以我犹豫不决考虑下发固定。
另外,为了帮助其他遇到此问题的人,涉及的usp10.dll版本是:
1.405.2416.1:这是文件夹中的版本Office10,也是导致 Crystal Reports 崩溃的版本。当您打印报表时,当 Crystal Reports 调用usp10.dll中的函数之一时,会发生访问冲突(我没有原始堆栈跟踪,但我认为这是该ScriptApplyDigitSubstitution函数)。
1.626.7600.16385:这是一个已知的良好版本,可以与 Crystal Reports 一起正常工作。这个版本好像是Windows 7默认安装的版本。
还有其他版本,例如默认安装在 Windows XP 中的System32文件夹中,也可以与 Crystal Reports 一起正常工作。