Rottytooth

Thursday, November 08, 2007

When calling .NET code from COM, how is the proper version of the .NET Framework determined?

The answer? Often it isn't! However, there's a way to force it to load the version you want.

Had a very annoying problem with VBA code (running in Excel) trying to load a .NET assembly (via a COM reference to a type library) and failing. It was a .NET 2.0 assembly. The strange thing was: on some machines it would load properly, while on others it would give the generic "xxxxxx or one of its dependencies could not be found" error at runtime.

To fix the problem, I went to one of the machines where I was getting the error, and broke out the under-appreciated Assembly Binding Log Viewer (a.k.a. fuslogvw -- it's installed with Visual Studio). This tool tracks which assemblies are loaded, and who the caller of each is; it's great for resolving bad references.

A few things to note about using fuslogvw:

  1. You're best off setting a custom log path -- the default path will not work on most machines -- and it will not tell you that it failed, the log will simply be empty.
  2. Set it to log all binds to disk, including successes, for the full picture of what's being loaded.
  3. When you're done, disable the log so it won't slow down assembly binding when you don't need it.

I set fuslogvw to log and ran my test VBA code in Excel. Then I refreshed the log and saw the assembly binding failure. The first few lines of output gave the whole story:


*** Assembly Binder Log Entry (11/7/2007 @ 11:24:07 AM) ***

The operation failed.
Bind result: hr = 0x80131107. No description available.

Assembly manager loaded from: C:\WINNT\Microsoft.NET\Framework\v1.1.4322\fusion.dll
Running under executable C:\Program Files\Microsoft Office\Office\EXCEL.EXE
--- A detailed error log follows.

The assembly manager for the 1.1 version of .NET was used. It attempted to load a 2.0 assembly, and failed.

I found very little on the web to address this (which is why I decided to post this). The fix is to set an Environment Variable for the default assembly manager to load: COMPLUS_Version, which should be set to the version of the .NET Framework you want: in this case v2.0.50727. Of course, Environment Variables can be set via the registry at: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment .

When making these changes, just be sure it doesn't break other apps that use COM Interop. :)

More info: Basic info on how the runtime locates assemblies here.

Labels: ,

0 Comments:

Post a Comment

<< Home