VSTO Word add-in DLL loading error - visual-studio

I've created a word add-in, which uses one of my DLL's. The application works fine when I'm running it in Visual Studio (both debug or release mode), however when I try starting Word on it's own (and the add-in is still present) and then proceed to trigger a method which loads the DLL, I get a DLL error as shown in the picture below. I'm quiet certain that the problem is not related to x86/x64 compatibility issues as I've set the platform target to x86 for all projects. (The version of Word used for testing is also 32-bit). Any ideas as to what the problem might be will be greatly appreciated, thanks in advance!

So after a day of Googling, I found my solution. It turns out that Word (and Office programs in general) moves your dll's into separate temporary directories - found in:
$User\AppData\Local\assembly\dl3
My dll depended on other resources in the same directory, but because it was being moved separately into this temporary directory then the dll could not be loaded. To get around this, I loaded the dll manually from the directory that it was installed in using:
System.Reflection.Assembly.LoadFile(string path)
You can get the directory that it was installed in with these lines of code:
System.Reflection.Assembly assemblyInfo = System.Reflection.Assembly.GetExecutingAssembly();
//Location is where the assembly is run from
string assemblyLocation = assemblyInfo.Location;
//CodeBase is the location of the ClickOnce deployment files
Uri uriCodeBase = new Uri(assemblyInfo.CodeBase);
string ClickOnceLocation = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString());

Related

".exe file has stopped working" when file isn't in solution folder - ScreenReaderAPIWrapper causing the crash

Running the solution without problems in Visual studio 2017, or directly through .exe file in solution folder (inside release and debug folders). But when the ".exe" file is not in the solution folder, it will crash and stop working.
I found that these lines are causing the issue:
ScreenReaderAPIWrapper.ScreenReader sc = new ScreenReaderAPIWrapper.ScreenReader();
sc.SayString(textDisplay.Text.ToString());
The ScreenReaderAPIWrapper library for .net you're using is a wrapper around another library called UniversalSpeech. There are several solutions alike out there, like Davy Kager's Tolk or Chris Toth's AccessibleOutput. All of these libraries make use of native APIs provided by corresponding screen reader modules (jfwapi.dll, saapi32.dll, NvdaController32.dll and others).
For these libraries to work, you have to provide all of the needed DLLs along with your executable, otherwise you'll get those errors about the exe file that stopped working.
If you need to distribute your program, consider using installer tools like NSIS or InnoSetup to pack all needed files into one single installer.

Visual Studio c++ 2015 runtime deployment with legacy application

I have a winforms .net4.5.2 application which depends on a c++\cli wrapper which is included in the VS project by reference. When the winforms application, that is built using Any CPU, is launched a assembly resolver is used to point out the correct platform dll for the reference and Assembly.Load(ed) in the platform specific folders in the root of the application folder i.e. \x64 or \x86.
This c++\cli is now built using the v140 platform toolset which depends on the Universal CRT dll:s. Looking here https://blogs.msdn.microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ I was able to locate the necessary dll:s (41 * 2 of them) and I did what I was told to copy them inside the \x86 and \x64 folders. Now since the change to v140 platform my application does not start anymore and ProcessMonitor file operations tell me the following:
SUCCESS C:\MyApp\x64\TheCLIWrapper.x64.dll
SUCCESS C:\MyApp\x64\ADependency.dll
SUCCESS C:\MyApp\x64\msvcp140.dll
SUCCESS C:\MyApp\x64\vcruntime140.dll
SUCCESS C:\MyApp\x64\api-ms-win-crt-runtime-l1-1-0.dll
NAME NOT FOUND C:\MyApp\ucrtbase.dll
How is this even possible if before assembly resolving my c++\cli wrapper I explicitly set the dll directory (using SetDllDirectory) to the C:\MyApp\x64 folder? By this I mean why is the loading process looking in C:\MyApp for the ucrtbase.dll?
Naturally, if all the 41 dlls of a specific platform are copied to the root C:\MyApp\ folder it works but this is not an option for me, nor is the installation of c++ runtime executable on the clients running the application.
Does anyone have an idea or any tips on how to solve this deployment problem?
So you basically wanna do x-xopy deployment with x86-dll's in MyApp\x86, and x64-dll's in MyApp\x64?
How about explicitly loading the dll's with LoadLibrary?
I used procmon to inspect where the UCRT DLLs were trying to load each other from. Noticed the paths it was searching did not include the path set from the earlier SetDllDirectory. No matter what I tried the paths it searched seemed to only include the default values.
The working directory was always included as per Dynamic-Link Library Search Order and the only solution I could get was to change the current working directory to the appropriate one, load the DLL with the UCRT requirement, and change it back. Nothing else worked (including changing PATH environment variable)
Note this is very much not threadsafe

How to handle legacy OCX files in a Visual Basic Project

I have inherited an old VBP project that is ostensibly usable in Visual Basic 6.
It has two .ocx files which, research seems to indicate, need to be registered with regsvr32. Loading VB6 onto a Windows XP installation seems to allow me to successfully register them both.
However, VB6 still chokes on them. When I load the project, two errors are logged:
Line 228: Class CvsInSightDisplayOcx.CvsInSightDisplay of control Camera1 was not a loaded control class.
Line 5841: Class Xtimer01.Xtimer of control Xtimer1 was not a loaded control class.
And, naturally, the project will not compile. What steps can I take to get these .ocx files to play well?
#Bob77's comment led me to a two part resolution.
1) One of the components needed to be formally installed. (Thankfully it was still available.)
2) Both needed to be manually removed from the .vdp file using Notepad, and added via the VB6 UI, through Project -> Components... and 'Browse...'

Visual Studio breakpoints break in the wrong source file (or multiple files simultaneously) if multiple files have the same name

In a team project I'm working on, setting a breakpoint in a file (say IdeasController.cs) will lead to erratic debugger behaviour if there's another file with the same name in the solution. I've reproduced the problem on several developers' workstations.
Example
I set a breakpoint in IdeasController.cs in our Web API:
Another file called IdeasController.cs exists in our separate MVC 4 web project. In the screenshot below, the debugger shows the Api->IdeasController source code, but the line highlight matches the code structure of Web->IdeasController. The breakpoint is duplicated, with one of them in the middle of a comment block.
The Breakpoint window shows the breakpoint in both files simultaneously:
On some workstations the debugger steps through the correct lines (regardless of the line highlight); on others it cheerfully steps through irrelevant lines (including comments and whitespace). I'm guessing this depends on which source file it chooses to display.
What I've tried
I've trawled the Internet. This kind of problem seems to occur when there's a mismatch between the debug file (*.pdb), the source file, and the compiled code. There are a lot of possible causes: duplicate file names (which can confuse the debugger[5]), outdated project build files, invalid solution cache, or incorrect build configuration.
These are the solutions I've found and tried:
Checked my build configuration.
Made sure the project isn't built in release mode.
Made sure we don't have code optimization enabled.
Made sure the project's debug module was loaded correctly. (Started debugging the project and checked Debug > Windows > Modules. Both assemblies are listed, not optimized, and have a symbol status of "Symbols loaded".)
Reset the debugging metadata & Visual Studio cache.
Closed Visual Studio and deleted the solution cache file (*.suo).[1]
Deleted each project's build output (the bin and obj folders). (For future reference: open the solution folder in Windows Explorer and type this in the search box: "type:folder AND (name:=bin OR name:=obj)".
Deleted the assembly cache folder (C:\Documents and Settings\<user>\Local Settings\Application Data\dl3).[2][3]
None of these had any effect. I can rename one of the files (without renaming the class) to temporarily work around the problem, but that's far from ideal.
Where I am now
Page 14 of my latest Google search. Suggestions would be much appreciated. :)
If no better alternatives exist, you could put the breakpoint in code:
System.Diagnostics.Debugger.Break();
Just don't forget to remove it afterwards...
I'm so glad I found this post, thought I was the only one and was going insane! I'm having the same problem in VS2012 with VB.Net and have tried everything the OP mentioned.
Unique naming of the files seems to be the only 100% fix that I've found. Disabling all breakpoints until the application has loaded and then re-enabling the breakpoints you need works most of the time. Breakpoints in Lambda functions can still give you issues.
I just had the exact same problem. What solved it for me was deleting the .suo files belonging to the solution that contained the affected project/source file.
I also deleted my local symbolcache but I don't think that had anything to do with it.
(My solution contains multiple projects, one file (DataAdapter.cs) in one project was affected by this (VisualStudio put my breakpoints in the pdb belonging to System.Data.DataAdapter). I opened the .csproj file directly and was able to correctly set the breakpoint.)
I had the same problem today. I was able to trace it back to the fact that I had forgotten to set the platform target to x86 while debugging. Unfortunately the others (x64 / Any CPU) can be problematic while debugging. At least VS 2008 doesn't like them. I guess this is yet another reason to stay away.
Some speculation... I think the debugger (while running a 64 bit app) somehow "steals" breakpoints away from a file in certain cases. For me it was because another assembly was loaded first which had the same file name. I was able to avoid the issue, even in 64 bit mode, if I first manually loaded the assembly with my breakpoints: Assembly.Load("MyAssemblyWithBreakpoints");
Hope this (my first stackoverflow contribution) helps.
Although renaming one of the files will work, I found that the simplest solution is to temporarily disable automatic loading of symbols for the "other" assembly.
Start the debugger and continue until you hit the erroneous breakpoint.
Find where the debugger actually set the breakpoint using the Call Stack window:
Right-click on the row with the yellow arrow and enable Show Module Names. (The row should also have the red breakpoint symbol on it.)
The assembly name is now visible on that row.
Find that assembly in the Modules window (Debug > Windows > Modules).
Right-click on the assembly and disable Always Load Automatically.
Stop the debugger.
Start debugging again.
By doing this, you're preventing the Visual Studio debugger from mapping the breakpoint to the wrong assembly. It will then load the symbols from the other [presumably] correct assembly first, therefore mapping the breakpoint to the correct assembly.
Why does this happen?
This seems to occur when two different symbol files (PDB files) — for two different assemblies — both reference a source file with the same name. Although the source files are completely different, the Visual Studio debuggger seems to get confused.
For example, imagine there are two different files both with the name IdeasController.cs. The first one compiles into assembly Api.dll, and the second one compiles into assembly Web.dll.
When the debugger loads symbols, it will either load Api.pdb or Web.pdb first. Let's say it loads Api.pdb first. Then even if you set a breakpoint in Web\IdeasController.cs, it will find a match for IdeasController.cs in Api.pdb. It then maps code from Web\IdeasController.cs to Api.dll. This won't map correctly, of course, and so you see all sorts of odd issues while debugging.
I just had this issue on Visual Studio 2017 (Version 15.9.7), were break points were skipped and the debugger just "jumped" over return statements etc.
After a while I noticed, that I've recently added a .runsettings file to the project - and it turned out, that in my case configuring the CodeCoverage data collector is causing this problem.
As soon as I removed this section:
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> ... </DataCollector>
from the .runsettings file, it worked like a charm again.
I just backed up and deleted the file and then added back to the project, that solved the problem. I just whish i did it before going through the beforementioned list :)
You may also try to Clean and Rebuild (not Build) all projects.
I was hitting this issue in Visual Studio 2015.
I had a sub-folder with a DLL I wanted to save as Version1. It seems even after removing the reference to that DLL, and then adding a reference to another project studio pulled in the existing reference and went to the wrong source file. I removed that DLL in the sub-folder then Studio got the correct source.
I found a helpful link on [MSDN that shows how to clear prior associated source files in studio at this link][1].
Summary:
In the Solution Explorer, right click on the solution name (ex: Solution ‘TestApplication’) and select Properties This will bring up the Solution Property Pages dialog
Under Common Properties, select Debug Source Files
In the Search these paths for source code files (Visual Studio .NET 2003) / Directories containing source code (Visual Studio 2005) box, add, remove and/or reorder the directories as desired
Click the OK button
I was having the same issue. In my case both the projects had same port numbers. I was able to resolve it by changing the port number of the project whose file's breakpoints were not hitting.
My guess is that IIS Express was caching the pdb file from the second project since both files had the same name, and the projects had the same port number.
What worked for me (VS2017) was disabling this option in Tools --> Options... --> Debugging --> General: "Require sources files to exactly match the original version", which is enabled by default but I had it turned on.
That was not enough though, I also had to manually remove obj and bin folders for all projects in solution.
Delete all the .pdb files of the project where the break point is hitting wrongly. This will solve the issue.
It happened to me (in VS 2008) to have two child breakpoint with the same memory address and the same associated file.
Those breakpoints were spawned at a certain time during the running of the process.
I noticed that I had duplicated .dll files in my project folders, and resolved removing the duplicated .dll, while keeping only one .dll per name in the debugging folder structure. (As example in my case I had /bin/Example.dll and /bin/Plug-in/Example.dll both present under my debug folder structure).
I had a very similar problem. In my case the problem was a different target .net framework in one of the projects causing VS2017 to wrongly load a source file (with the same name) of another project, not the one being activated with
ObjectHandle handle = Activator.CreateInstance
Changing the project's target framework to be the same in all projects fixed it.
I had a similar issue with the breakpoint being set in another file with the same filename in a different project.
It was caused by the fact that the debugging was started for that other project, while it was not started for the project where I tried to set the breakpoint. The breakpoint creation worked correctly after doing the Debug > Start New Instance for the intended project.

Are there reasons why DLL redirection won't work other than the presence of a manifest?

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).
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.
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.
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.dll or through the Report Viewer control.
In the past, we have resolved this issue by copying a known good version of usp10.dll into our application's directory and creating an .local file to enable DLL redirection. At the customer site, I tried this, and also tried the alternate approach of creating a .local folder for our EXE and placing the usp10.dll in there, but neither approach worked on the machine I was connected to.
I did notice that usp10.dll is 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 documentation states 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).
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 LoadLibrary calls for usp10.dll pointing to a folder other than the redirected folder, but some calls were apparently redirected, so I'm not sure what that means either).
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 answer and this blog post by 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.
EDIT #2: After playing around with Dependency Walker some 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 Walker and 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.dll from 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 LoadLibrary calls 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.
I'm still not 100% clear why the .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.
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 same copy?
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 exactly the scenario they were developed to solve.
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).
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.
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.
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).
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.
So, your problem confuses me. The usp10.dll used should be
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.
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 :
the one in your application folder, because this seems to be the one case where .local files might apply.
Given that the presence of the DLL in KnownDLLs is inhibiting the functionality of .local, and given that Crystal reports dlls are pathalogical ...
All I can suggest is:
This thread contains a function called PatchIAT - import it into your code.
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.
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.
Disable antialiasing for a specific GDI device context
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 from C:\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.
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.
It turns out the when Crystal Reports calls LoadLibrary, it checks the following folders for usp10.dll:
If HKEY_LOCAL_MACHINE\SOFTWARE\Business Objects\Suite 11.0\Crystal Reports\CommonFiles is present in the Registry, it calls LoadLibrary using that path.
If the registry key is not present, or usp10.dll doesn't exist in that folder, Crystal Reports will call LoadLibrary with C:\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) to LoadLibrary, which then causes Windows to load the copy in 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.dll that was in the Office10 folder, even after putting a copy of usp10.dll in 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.
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.dll to that folder, so it was still picking up the copy in the Office10 folder.
The final workaround given to the customer was stupidly simple:
Copy the version of usp10.dll from the System32 into C:\Program Files\Common Files\Business Objects\3.0\bin.
Run the crdeploy.reg file in the bin folder to ensure that the CommonFiles registry key exists and is pointing to C:\Program Files\Common Files\Business Objects\3.0\bin.
I had originally thought putting a copy of usp10.dll into 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.
Also, in case it helps anyone else experiencing this problem, the versions of usp10.dll involved were:
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 the ScriptApplyDigitSubstitution 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.
There are other versions, such as installed by default in Windows XP in the System32 folder that also work fine with Crystal Reports.
I just had a similar issue on a TS running Server 2008 R2. Error from Event log:
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.
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?)
Why can't you call LoadLibrary("usp10.dll") yourself as the first thing you do at startup?

Resources