Monday, April 13, 2009

Team Foundation Server (TFS) Customizations in x64 Environments

While testing one of the Visual Studio Team System (VSTS) extensions I wrote I came across a scenario where the assembly was failing to load under the 64-bit version of Windows 7. It turns out that by default when one creates a project in Visual Studio 2008 the target is set to Any CPU. This in turn sets the Processor Architecture of the resulting assembly to MSIL, which essentially lets the Operating System (OS) decide which .NET Framework version and flavor to use (for all intense and purposes). This causes a problem when writing extensions for VSTS such as Work Item Tracking Custom Controls and other applications that leverage the Team Foundation Server SDK.

When loading such an assembly (of type MSIL, the default created when using the target Any CPU) in a x64 environment it will use the corresponding .NET Framework assemblies, which are in this case also 64-bit. The problem is that since all Team Foundation assemblies are 32-bit (or specifically of type x86) the mix causes the application to fail loading, in my case with the following error (as displayed in the Windows Event Log).

Faulting application ProcessTemplateItemDeployer.exe, version 1.0.0.0, time stamp 0x49de2a19, faulting module KERNEL32.dll, version 6.0.6001.18000, time stamp 0x4791ada5, exception code 0xe0434f4d, fault offset 0x000000000002649d, process id 0x%9, application start time 0x%10.

As you can see this is not very helpful. More details can be retrieved, however, from the error dialog itself that shows up when the application falters. In my case, the following snippet is displayed (extras removed for brevity).

See the end of this message for details on invoking just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
System.InvalidProgramException: Common Language Runtime detected an invalid program.
at InCycle.Tools.Forms.ImportProcessTemplateItem.ImportProcessTemplateItem_Load(Object sender, EventArgs e)
… (extra text removed …)
************** Loaded Assemblies **************
mscorlib Assembly Version: 2.0.0.0 Win32 Version: 2.0.50727.3521 (NetFXspW7.050727-3500)
CodeBase: file:///C:/Windows/Microsoft.NET/Framework64/v2.0.50727/mscorlib.dll

What is interesting here is the last line. Notice that the mscorlib.dll that my application is referencing comes from the Framework64 folder of the .NET 2.0 Framework.

The solution I found, after quite a bit of research and trial and error, is to force the extensions to specifically target x86. Doing so forces the OS to load the 32-bit framework assemblies at run time, even in a 64-bit OS.

Refer to the article How to: Optimize an Application for a Specific CPU Type on MSDN for specific details on how to change the Processor Architecture.

1 comment:

TBeaulieu said...

Yeah, we came across this issue with TFSDeployer. Had to download the source, switch it to x86 and recompile.