Mailbag: How to debug 1935 errors with HRESULT 0x80131047 in an MSI-based setup

Question:

I am attempting to create an MSI-based setup for my application.  This application needs to install some assemblies to the global assembly cache (GAC), and when I build an MSI and try to install it, setup fails with a 1935 error with HRESULT value 0x80131047 (-2146234297).

I found your article describing 1935 errors, and according to that article, this HRESULT value corresponds to a FUSION_E_INVALID_NAME error that means "The given assembly name or code-base is invalid."

This error description does not make much sense to me.  How can I narrow down the root cause of this error and fix my MSI so that it will install correctly? 

Answer:

In most of the cases I have seen a 1935 error with HRESULT value 0x80131047 (-2146234297), the root cause has been a mismatch between the assembly identity information listed in the MsiAssemblyName table of the MSI and the assembly identity information in the assembly itself.

In order to narrow this error down further, I recommend first trying to manually install the assembly to the GAC and then uninstall it from the GAC using the tool gacutil.exe that is included in the .NET Framework SDK and Visual Studio.  Doing this will determine whether or not the problem is in the assembly or in the MSI, and it will also show you the full assembly identity for the assembly as well.  You can use the following steps to do this:

  1. Click on the Start menu, choose Run, type cmd and click OK
  2. Run a command like the following:  "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /i <full path to the assembly>
  3. You should see output like the following: >"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /i MyAssembly.dll
    Microsoft (R) .NET Global Assembly Cache Utility. Version 2.0.50727.42
    Copyright (c) Microsoft Corporation. All rights reserved.
    Assembly successfully added to the cache
  4. Run a command like the following:  "C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /u <name of assembly>
  5. You should see output like the following:

If the assembly can be successfully installed to and uninstalled from the GAC using gacutil.exe, then there is likely something incorrectly authored in the MsiAssemblyName table of the MSI.  The next step is to do the following to try to narrow down the MSI authoring issue:

  1. Open the MSI in a tool such as Orca.exe
  2. Locate the entries in the MsiAssemblyName table for the assembly that fails with a 1935 error during setup
  3. Compare the attributes listed for this assembly in the MsiAssemblyName table with the attributes listed when running gacutil.exe for the assembly.
  4. Validate that all of the attributes listed when running gacutil.exe (for example, the highlighted items that appear in step 5 listed above) also appear in the MsiAssemblyName table for this assembly.  All values must match exactly

It will not cause problems if there are extra values in the MsiAssemblyName table that do not appear when running gacutil.exe.  However, none of the values listed when running gacutil.exe can be missing from the MsiAssemblyName table, and none of the values can contain different data (such as misspellings, non-matching version numbers, different public key tokens, etc)

For reference, assemblies built with the .NET Framework 1.0 and 1.1 contain the following attributes that combine to form the assembly identity: Name, Version, Culture, PublicKeyToken.  An MSI that installs .NET Framework 1.0/1.1 assemblies to the GAC must contain all 4 of these attributes for each assembly in the MsiAssemblyName table.

Assemblies built with the .NET Framework 2.0 contain the following attributes that combine to form the assembly identity: Name, Version, Culture, PublicKeyToken, ProcessorArchitecture.  It is important to note that the ProcessorArchitecture attribute is new and will only exist in assemblies created with the .NET Framework 2.0 or later.  An MSI that installs .NET Framework 2.0 assemblies to the GAC must contain all 5 of these attributes for each assembly in the MsiAssemblyName table.

It is possible to install both .NET Framework 1.0/1.1 and .NET Framework 2.0 assemblies to the GAC in the same MSI.  You will need to make sure that the attributes are correct for each assembly based on what version of the .NET Framework they were built against.  A common problem I have seen in this scenario is to leave off the ProcessorArchitecture attribute for .NET Framework 2.0 assemblies or to include it for .NET Framework 1.0/1.1 assemblies.