windows 除了清单的存在之外,还有其他原因导致 DLL 重定向不起作用吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3400168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are there reasons why DLL redirection won't work other than the presence of a manifest?
提问by Mike Spross
We have a legacy VB6 application that uses Crystal Reports XI to generate printed reports. We've found through experience that the Crystal Reports print engine crashes if it picks up the wrong version of usp10.dll(the Windows Uniscribe library).
我们有一个旧的 VB6 应用程序,它使用 Crystal Reports XI 来生成打印报告。我们通过经验发现,如果 Crystal Reports 打印引擎选择了错误版本的usp10.dll(Windows Uniscribe 库),它就会崩溃。
One customer is consistently having printing issues on their Windows 7 machines (running Windows 7 Enterprise, 32-bit). However, we have a few other customers running various editions of Windows 7 that are not having any problems.
一位客户在其 Windows 7 计算机(运行 Windows 7 Enterprise,32 位)上始终遇到打印问题。但是,我们还有一些其他客户在运行各种版本的 Windows 7,但没有出现任何问题。
On one of the machines that was having printing issues, I noticed that there was an older version of usp10.dll
(one incompatible with Crystal Reports XI) in the folder C:\Program Files\Common Files\Microsoft Shared\Office10\
. I'm not sure what application installed these files, because the customer doesn't have Office 2002 installed (so I assume another application installed them). However, I temporarily renamed the file and our application was able to print correctly, so it seems that our application was loading that version of the file originally, which was causing the crashes.
在其中一台出现打印问题的机器上,我注意到usp10.dll
文件夹中有一个旧版本(一个与 Crystal Reports XI 不兼容)C:\Program Files\Common Files\Microsoft Shared\Office10\
。我不确定哪个应用程序安装了这些文件,因为客户没有安装 Office 2002(所以我假设另一个应用程序安装了它们)。但是,我暂时重命名了该文件并且我们的应用程序能够正确打印,因此看起来我们的应用程序最初正在加载该版本的文件,这导致了崩溃。
The crash only happens the moment the user tries to print a report. Our application has direct dependencies on craxdrt.dll(the Crystal Reports ActiveX Designer Runtime library) and crviewer.dll(the Crystal ActiveX Report Viewer library), and the crash happens whether we print directly through craxdrt.dllor through the Report Viewer control.
崩溃仅在用户尝试打印报告时发生。我们的应用程序直接依赖于craxdrt.dll(Crystal Reports ActiveX 设计器运行库)和crviewer.dll(Crystal ActiveX 报表查看器库),无论我们是直接通过craxdrt.dll打印还是通过报表查看器控件打印,都会发生崩溃。
In the past, we have resolved this issue by copying a known good version of usp10.dllinto our application's directory and creating an .localfile to enable DLL redirection. At the customer site, I tried this, and also tried the alternate approach of creating a .localfolder for our EXE and placing the usp10.dllin there, but neither approach worked on the machine I was connected to.
过去,我们通过将已知良好版本的usp10.dll复制到我们的应用程序目录并创建一个.local文件以启用 DLL 重定向来解决此问题。在客户站点,我尝试了这个,还尝试了为我们的 EXE创建一个.local文件夹并将usp10.dll放在那里的替代方法,但两种方法在我连接的机器上都不起作用。
I did notice that usp10.dllis a "known" DLL in Windows (it has an entry in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs
), but I tested our application on another Windows 7 machine (running Professional Edition, 32-bit) here that also had the DLL listed as a known DLL in the registry, and by using Dependency Walker, I could see that the redirection was working on that computer. This is somewhat confusing, since the Microsoft documentationstates that known DLL's cannot be redirected. Also, as I implied in the question title, our main EXE does not use a manifest file (the Microsoft documentation states that the presence of a manifest, embedded or standalone, disables DLL redirection).
我确实注意到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 重定向)。
So, my question is, is there any other reason why DLL redirection would work on some machines and not others, and does this have anything to do with differences between Windows 7 and Windows XP? I had considered deleting everything in the KnownDLLs
registry key, but since the redirection was working on a machine here that had the same set of KnownDLLs
, I'm not sure that would actually resolve the issue, and I don't want to delete that key if I don't need to. I haven't yet had a chance to connect to the customer's machine again to run Dependency Walker, but I'm not sure I would be able to interpret its logs anyway (even on the machine where it was working, I saw a lot of LoadLibrarycalls for usp10.dllpointing to a folder other than the redirected folder, but some calls were apparently redirected, so I'm not sure what that means either).
所以,我的问题是,DLL 重定向在某些机器上起作用而不是在其他机器上起作用是否还有其他原因,这与 Windows 7 和 Windows XP 之间的差异有什么关系?我曾考虑删除的所有KnownDLLs
注册表项,但由于转产在这里工作的机器的同一组的上KnownDLLs
,我不知道这实际上解决这个问题,我不想删除键,如果我不需要。我还没有机会再次连接到客户的机器来运行Dependency Walker,但我不确定我是否能够解释它的日志(即使在它工作的机器上,我也看到了很多LoadLibrary调用usp10.dll指向重定向文件夹以外的文件夹,但有些调用显然已重定向,所以我也不确定这意味着什么)。
EDIT: I should have also mentioned that every computer we've checked also has another copy of usp10.dll
in the System32
folder. Looking at Chris's answerand this blog postby Larry Osterman explaining a bit more about how known DLLs work, I realized that that probably doesn't factor into the problem at all, since our program isn't loading the copy of usp10.dll
that is in the System32
folder.
编辑:我还应该提到我们检查过的每台计算机usp10.dll
在System32
文件夹中还有另一个副本。看着克里斯的回答和这篇博客文章由拉里·奥斯特曼解释多一点有关已知的DLL是如何工作的,我意识到这可能不会纳入到在所有的问题,因为我们的程序没有加载的副本usp10.dll
是在System32
文件夹。
EDIT #2: After playing around with Dependency Walkersome more on my VB6 development machine (Windows XP SP3), where the printing has always worked, I was able to glean some information. I profiled our application in Dependency Walkerand set it to log full path names, and it looks like one of the Crystal Reports dependencies (another Crystal Reports DLL) tries to load usp10.dllfrom multiple (hard-coded) paths before giving up and just asking for it by filename. It turns out that it tries to load it from the Crystal Reports bin
folder first, then tries to load it from from C:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll
. If it can't find it at either location, it just asks Windows for usp10.dll
(which will grab the one in System32
). But even this isn't consistent. Sometimes it asks for the file in the Office10
folder, and then appears to ignore the fact that it couldn't find the file, while other times there are a series of LoadLibrarycalls where it looks like the Crystal Reports code is actively looking for alternate copies of the file in different locations. Even more confusing is that at least one of the Crystal Reports components looks like it actually has a load-time dependency on usp10.dll, so that component always seems to get the copy in System32
.
编辑 #2:在我的 VB6 开发机器(Windows XP SP3)上玩了更多依赖 Walker之后,打印一直有效,我能够收集一些信息。我在Dependency Walker 中分析了我们的应用程序并将其设置为记录完整路径名,看起来 Crystal Reports 依赖项之一(另一个 Crystal Reports DLL)在放弃之前尝试从多个(硬编码)路径加载usp10.dll只是通过文件名要求它。事实证明,它首先尝试从 Crystal Reportsbin
文件夹加载它,然后尝试从C:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll
. 如果在任何一个位置都找不到它,它只会向 Windows 询问usp10.dll
(它会在System32
)。但即使这样也不一致。有时它会要求文件Office10
夹中的文件,然后似乎忽略了它找不到文件的事实,而其他时候有一系列LoadLibrary调用,看起来 Crystal Reports 代码正在积极寻找替代副本不同位置的文件。更令人困惑的是,至少有一个 Crystal Reports 组件看起来实际上对usp10.dll具有加载时依赖性,因此该组件似乎总是在.dll中获取副本System32
。
I'm still not 100% clear whythe .local
redirection wouldn't work in this situation on this customer's computers, but I think that partly explains why this particular customer is having problems, since all of the computers with the problem have an Office10
folder with an apparently incompatible version of usp10.dll
in it.
我还没有100%清除为什么在.local
重定向将在该客户的计算机上这种情况不会工作,但我认为这部分解释了为什么这个特殊的客户遇到的问题,因为所有有问题的计算机上有一个Office10
文件夹的显然不兼容的版本usp10.dll
在里面。
But, once again, I'm still left with the basic question: if these components are looking for this file in so many different places, how can I guarantee that they will all use the samecopy?
但是,再一次,我仍然有一个基本问题:如果这些组件在这么多不同的地方寻找这个文件,我怎么能保证它们都使用相同的副本?
采纳答案by Mike Spross
The solution was actually pretty simple, but it took me a while to figure out why it worked.
解决方案实际上非常简单,但我花了一段时间才弄清楚它为什么起作用。
On the customer machine, I copied usp10.dll fromC:\Windows\System32
(which is known-good version) into the folder C:\Program Files\Common Files\Business Objects\3.0\bin
(where most of the Crystal components are installed). I then ran a crdeploy.reg
file that was already present in in the bin
folder: this file adds a HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports
key to the Registry and sets the value CommonFiles
to C:\Program Files\Common Files\Business Objects\3.0\bin
.
在客户机器上,我将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
.
Since I couldn't connect to the customer's machine earlier today, I did some more testing of the issue on a Windows 7 virtual machine. Like I mentioned in one of my edits, on this computer Crystal Reports never looked in the C:\Program Files\Common Files\Business Objects\3.0\bin
directory for usp10.dll, so it would immediately try to load the copy in the C:\Program Files\Common Files\Microsoft Shared\Office10
folder.
由于我今天早些时候无法连接到客户的机器,因此我在 Windows 7 虚拟机上对该问题进行了更多测试。就像我在我的一次编辑中提到的那样,在这台计算机上,Crystal Reports 从未查看过usp10.dll的C:\Program Files\Common Files\Business Objects\3.0\bin
目录,因此它会立即尝试加载文件夹中的副本。C:\Program Files\Common Files\Microsoft Shared\Office10
It turns out the when Crystal Reports calls LoadLibrary
, it checks the following folders for usp10.dll:
事实证明,当 Crystal Reports 调用时LoadLibrary
,它会检查以下文件夹中是否存在usp10.dll:
If
HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports\CommonFiles
is present in the Registry, it callsLoadLibrary
using that path.If the registry key is not present, or usp10.dlldoesn't exist in that folder, Crystal Reports will call
LoadLibrary
withC:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll
as the path.If the file isn't found in the
Office10
folder, it passes just the filename (usp10.dll
) toLoadLibrary
, which then causes Windows to load the copy inSystem32
.
如果
HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports\CommonFiles
存在于注册表中,则LoadLibrary
使用该路径调用。如果注册表项不存在,或者该文件夹中不存在usp10.dll,Crystal Reports 将调用
LoadLibrary
withC:\Program Files\Common Files\Microsoft Shared\Office10\usp10.dll
作为路径。如果在文件
Office10
夹中找不到该文件,它只会将文件名 (usp10.dll
)传递给LoadLibrary
,然后导致 Windows 将副本加载到System32
.
So, on my test Windows 7 machine, I didn't have the CommonFiles
registry key set, so Crystal Reports always loaded the version of usp10.dllthat was in the Office10
folder, even after putting a copy of usp10.dllin C:\Program Files\Common Files\Business Objects\3.0\bin
. Once I set the registry key to point to the right place, Crystal Reports loaded the correct version of the file.
所以,我测试的Windows 7机器上,我没有足够的CommonFiles
注册表键设置,所以水晶报表总是被加载的版本的usp10.dll那是在Office10
文件夹中,甚至把副本后的usp10.dll中C:\Program Files\Common Files\Business Objects\3.0\bin
。一旦我将注册表项设置为指向正确的位置,Crystal Reports 就会加载正确版本的文件。
On the customer's machine, the registry already had the CommonFiles
path set to the right folder, but our application's setup program wasn't installing usp10.dllto that folder, so it was still picking up the copy in the Office10
folder.
在客户的机器上,注册表已将CommonFiles
路径设置为正确的文件夹,但我们应用程序的安装程序并未将usp10.dll安装到该文件夹中,因此它仍在Office10
文件夹中获取副本。
The final workaround given to the customer was stupidly simple:
给客户的最终解决方法非常简单:
Copy the version of usp10.dllfrom the
System32
intoC:\Program Files\Common Files\Business Objects\3.0\bin
.Run the
crdeploy.reg
file in thebin
folder to ensure that theCommonFiles
registry key exists and is pointing toC:\Program Files\Common Files\Business Objects\3.0\bin
.
的版本复制的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
.
I had originally thought putting a copy of usp10.dllinto the bin
folder would fix the problem on the customer's machines, but like I said, this didn't work on my Windows 7 test machine because I was missing the CommonFiles
registry key, so I was hesitant to consider the issued fixed.
我原本以为将usp10.dll的副本放入bin
文件夹可以解决客户机器上的问题,但就像我说的,这在我的 Windows 7 测试机上不起作用,因为我缺少CommonFiles
注册表项,所以我犹豫不决考虑发行固定。
Also, in case it helps anyone else experiencing this problem, the versions of usp10.dllinvolved were:
此外,为了帮助遇到此问题的其他人,所涉及的usp10.dll版本为:
1.405.2416.1: This is the version in the
Office10
folder, and the one that causes Crystal Reports to crash. When you print a report, an access violation occurs when Crystal Reports calls one of the functions in usp10.dll(I don't have the original stacktrace, but I think it was theScriptApplyDigitSubstitution
function).1.626.7600.16385: This is a known good version that works correctly with Crystal Reports. This version seems to be the one installed in Windows 7 by default.
1.405.2416.1:这是
Office10
文件夹中的版本,也是导致Crystal Reports崩溃的版本。当您打印报告时,当 Crystal Reports 调用usp10.dll 中的一个函数(我没有原始堆栈跟踪,但我认为是该ScriptApplyDigitSubstitution
函数)时,会发生访问冲突。1.626.7600.16385:这是一个已知的良好版本,可以与 Crystal Reports 一起正常工作。此版本似乎是默认安装在 Windows 7 中的版本。
There are other versions, such as installed by default in Windows XP in the System32
folder that also work fine with Crystal Reports.
还有其他版本,例如默认安装在 Windows XP 中的System32
文件夹中,也可以与 Crystal Reports 配合使用。
回答by Chris Becke
My first thought: .manifest files and all they imply were added to windows XP in 2002/2003. Why the @#$% does your app - and the libraries your app uses for that matter - not use this technology to solve this little "dll-hell". It is exactlythe scenario they were developed to solve.
我的第一个想法是:.manifest 文件以及它们所暗示的所有内容都是在 2002/2003 中添加到 Windows XP 中的。为什么@#$% 会影响您的应用程序 - 以及您的应用程序为此使用的库 - 不使用这项技术来解决这个小小的“dll-hell”问题。这正是它们被开发用来解决的场景。
Next, im pretty sure that "KnownDlls" only covers dlls that the OS actually finds in System32. Finding dll's in random path locations (as in a Office2002 folder) i would hope at least would fail some internal sanity check (is-the-dll-a-real-KnownDlls-candidate) test. And the PATH is searched after system folders, so by the time a usp10.dll is found in ...\Office10\ - it' cant be a real known dll (by definition).
接下来,我很确定“KnownDlls”仅涵盖操作系统在 System32 中实际找到的 dll。在随机路径位置(如在 Office2002 文件夹中)查找 dll,我希望至少会在某些内部健全性检查(is-the-dll-a-real-KnownDlls-candidate)测试中失败。并且在系统文件夹之后搜索 PATH,因此当在 ...\Office10\ 中找到 usp10.dll 时 - 它不可能是真正已知的 dll(根据定义)。
Next, Im also sure that the .local file isn't doing what you think it is. The documentation for .local files makes no sense at all because all it really says is, the search order for dlls after a .local file is applies, is exactly the default search order for dll's normally - the exe folder is always searched BEFORE system folders anyway.
接下来,我还确定 .local 文件没有按照您的想法行事。.local 文件的文档完全没有意义,因为它真正说的是,应用 .local 文件后 dll 的搜索顺序,正是 dll 通常的默认搜索顺序 - 始终在系统文件夹之前搜索 exe 文件夹反正。
The only time .local actually makes a potential difference is when an application uses an explicit path to load a dll in a call to loadLibrary (or uses the altered search path flag to LoadLibrary or uses the SetDllSearchDirectory API). All cases where the exe or dll doing the loading is choosing a very specific dll - that you the app author wants to override in some way. .local files cannot (Seem to me anyway) change the search behaviour for any dll files that are specified by just their name.
.local 真正产生潜在差异的唯一时间是当应用程序在调用 loadLibrary 时使用显式路径加载 dll(或使用更改的 LoadLibrary 搜索路径标志或使用 SetDllSearchDirectory API)。执行加载的 exe 或 dll 选择一个非常特定的 dll - 应用程序作者希望以某种方式覆盖的所有情况。.local 文件不能(在我看来)更改仅由其名称指定的任何 dll 文件的搜索行为。
So, if usp10.dll is installed into system32, its probably going to be picked up as a KnownDll and then used - despite your local copy (and .local file). If its somewhere else on the path, the copy in your exe's folder should be used first anyway - (assuming LoadLibrary("usp10.dll") is the way the dll is loaded).
因此,如果将 usp10.dll 安装到 system32 中,则它可能会作为已知的 Dll 被拾取然后使用 - 尽管您的本地副本(和 .local 文件)。如果它在路径上的其他地方,则无论如何都应该首先使用 exe 文件夹中的副本 - (假设 LoadLibrary("usp10.dll") 是加载 dll 的方式)。
Even if you go to all the effort of creating an assembly to contain your known-good usp10.dll, and then made your app dependent on that, I still think that a fully qualified path passed to LoadLibrary will defeat any search logic at all - including looking for the dll in the list of dependent assemblies.
即使您竭尽全力创建程序集以包含已知良好的 usp10.dll,然后让您的应用程序依赖它,我仍然认为传递给 LoadLibrary 的完全限定路径将完全击败任何搜索逻辑 -包括在依赖程序集列表中查找 dll。
So, your problem confuses me. The usp10.dll used should be
所以,你的问题让我很困惑。使用的usp10.dll应该是
- the one in system32 if present (because of KnownDlls overring the one in your exe's folder)
- the one in your application folder, because search logic will always find this one first if KnownDlls is a miss.
- 如果存在 system32 中的那个(因为KnownDlls覆盖了您的exe文件夹中的那个)
- 应用程序文件夹中的那个,因为如果KnownDlls 未命中,搜索逻辑将始终首先找到这个。
unless usp10.dll is actually a com dll, or there is a fully qualified path to it in the registry that consumers use to load it, in which case the one loaded should be :
除非 usp10.dll 实际上是一个 com dll,或者在消费者用来加载它的注册表中有一个完全限定的路径,在这种情况下,加载的应该是:
- the one in your application folder, because this seems to be the one case where .local files might apply.
- 应用程序文件夹中的那个,因为这似乎是 .local 文件可能适用的一种情况。
Given that the presence of the DLL in KnownDLLs is inhibiting the functionality of .local, and given that Crystal reports dlls are pathalogical ...
鉴于已知DLL中DLL的存在抑制了.local的功能,并且鉴于Crystal报告dll是病态的......
All I can suggest is:
我只能建议:
This thread contains a function called PatchIAT - import it into your code.
该线程包含一个名为 PatchIAT 的函数 - 将其导入到您的代码中。
Before using any functionality in the Crystal Reports dlls (That causes them to go looking for usp10.dll) - call LoadLibrary to get a handle to the dll, then call PatchIAT on the handle, to redirect the dll's call to LoadLibrary to a function your EXE implements.
在使用 Crystal Reports dll 中的任何功能之前(这会导致他们寻找 usp10.dll) - 调用 LoadLibrary 以获取 dll 的句柄,然后在句柄上调用 PatchIAT,将 dll 对 LoadLibrary 的调用重定向到您的函数EXE 实现。
In your EXEs LoadLibraryThunk procedure, pass on any calls to the system's LoadLibrary, unless its for an explicit path to usp10.dll - on those calls - return an error code.
在您的 EXE 的 LoadLibraryThunk 过程中,将任何调用传递给系统的 LoadLibrary,除非它是 usp10.dll 的显式路径 - 在这些调用中 - 返回错误代码。
回答by Colin Nesbit
I just had a similar issue on a TS running Server 2008 R2. Error from Event log:
我刚刚在运行 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
I tried copying usp10.dll from \Windows\System32 into C:\Program Files (x86)\Common Files\Business Objects\3.0\bin. Then ran the crdeploy.reg file but had to manually update the regkey to include (x86) due to 64bit OS on server. The Crystal Reports app still wouldn't recognize the DLL, it kept looking in the \Office10 folder. So I just renamed the copy of the DLL in that folder then copied from \System32 again. That worked like a charm, also the file versions on the DLL were exactly the same that Mike Spross posted.
我尝试将 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 发布的完全相同。
回答by Anders
It does not seem like a good idea to me to have extra copies that windows does not know about (How will it get updated?)
拥有 Windows 不知道的额外副本对我来说似乎不是一个好主意(它将如何更新?)
Why can't you call LoadLibrary("usp10.dll")
yourself as the first thing you do at startup?
为什么你不能把LoadLibrary("usp10.dll")
自己作为你在启动时做的第一件事?