Proposed Workaround for C++/CLI Assembly Signing Issue with VS2010 SP1

Hi, my name is Amit Mohindra and I’m Program Manager with the MS Visual C++ team.

Recently we were made aware of a change in SP1 which affected the signing process for assemblies (C++/CLI assemblies) as part of the following forum post:

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/4b8f353d-8153-45d6-b286-10403cdf159a?prof=required

The issue in SP1 would affect folks who are using switches on the linker to sign the assemblies as part of their build. To sign assemblies you have to explicitly set the this property by right clicking on the project to bring up the properties dialog and then under Configuration Properties->Linker->Advanced set the “Key File” property to use a signing key. By default this property is empty so if you haven’t explicitly set it you should be unaffected.

In case you are using the linker switches in your CLI projects to sign the final assembly then please follow the contents of this blog to unblock yourself.

We are very sorry for the inconvenience caused by this assembly signing issue. We recognize that this change in SP1 has introduced an unintentional breaking change. This is indeed a bug in VS2010 SP1.

I will start by giving you a little bit of background into what the issue was in VS2010 RTM, how our change in SP1 broke your projects and then finally the workaround you could apply to unblock yourselves.

 

Background

  1. VS2010 RTM
    1. Assemblies built using C++ projects were not getting signed at all.
      1. This was happening since mt.exe would invalidate the signature performed by the preceding Link step (which signs the binary). This is expected behavior.
      2. To counter the invalidation the build process runs and additional “LinkEmbedManifest” step to re-sign the assembly after mt.exe is done embedding the manifest.
      3. However, in VS2010 RTM step 1.a.B was being skipped. Thus, the assemblies were not getting signed.
    2. So we recommended a workaround to run “sn.exe –R <assembly> <KeyFile>” (e.g. sn -R debugCLRConsole.exe C:mykey.snk)  as part of the custom build step and to sign the assembly.
  2. VS2010 SP1 (fix that broke you)
    1. The main reason why “LinkEmbedManifest” step was getting skipped in VS2010 RTM was that during the build process our decision logic to trigger this step did not have enough information. The decision logic required evaluated values for “Key File” and “Delay Sign” (properties on the Linker). These values were stored as “Item Definition Group”  (IDG) in the project file and IDG’s are evaluated at a later stage than the decision point and thus were unavailable.
    2. To fix the issue we made “Key File” and “Delay Sign” MSBuild properties (<PropertyGroups>) instead and since MSBuild properties are evaluated early on we would now be able to decide whether to run “LinkEmbedManifest” step or not. With this change we would have eliminated the need of a custom build step (as suggested in above in 1.a.B)
    3. As part of the SP1 readme (http://go.microsoft.com/fwlink/?LinkId=210711 – section 2.4.1.2) we suggested refactoring of the project to make signing work. The suggestion was to redefine the “Key File” and “Delay Sign” property for the project using the IDE.
    4. However there were two issues with this solution:
      1. First, a typo in one our build files makes the above suggestion not work when you are targeting the Win32 configurations to build your projects.
      2. Second, we did not recognize that people using the old method and the VS2010 RTM workaround (mentioned above in 1.a.B) would be broken.

 

Workaround

The following workaround enables you to fix the two issues described above in 2.d.A and 2.d.B. You can work around this issue in two ways.

1. Change each project in your solution and redefine the “Key File” and “Delay Sign” properties on the linker. To do that follow these steps:

· Fix the typo in the build process (2.d.A):

  1. Open cmd prompt as administrator
  2. Go to %ProgramFiles(x86)%MSBuildMicrosoft.Cppv4.0PlatformsWin32
  3. Run “notepad Microsoft.Cpp.Win32.targets” (x64 targets are fine)
  4. Find the “LinkEmbedManifest” target (search for <Target Name=”LinkEmbedManifest”)
  5. Under the above target and in the task “<Link” perform the following steps.
  6. Change property  DelaySign
    1. From :       DelaySign  =”%(Link.DelaySign)”
    2. To :         DelaySign  =”$(LinkDelaySign)”
  7. Change property  KeyFile
    1. From :       KeyFile    =”%(Link.KeyFile)”
    2. To:         KeyFile    =”$(LinkKeyFile)”

· Redefine the “Key File” and “Delay Sign” properties used for signing your project (2.d.B):

  1. Right click on your project to bring up the properties page.
  2. Go to Configuration Properties->Linker->Advanced
  3. Overwrite the property “Key File” with your original key file. (for e.g. myfile.snk)
  4. This workaround eliminates the need of a custom build step (as described in background section VS2010RTM-1.2)
  5. If you want to use the same project in VS2010 RTM and VS2010 SP1 make sure that when you redefine these properties they match their original value as set in VS2010 RTM.

2. Or, If you have a lot of projects and don’t want do step 1 (above) , alternatively you could make the following changes to resurrect your VS2010 RTM behavior:

  1. Open cmd prompt as administrator
  2. Go to “%ProgramFiles(x86)%MSBuildMicrosoft.Cppv4.0PlatformsWin32
  3. Run “notepad Microsoft.Cpp.Win32.targets
  4. Move to “Link” target (search for <Target Name=”Link”)
  5. Add the following lines right after the first  “<PropertyGroup>” definition  and before the “<Link” task
    <PropertyGroup>
        <LinkDelaySign Condition=”‘$(LinkDelaySign)’ == ””>%(Link.DelaySign)</LinkDelaySign>
        <LinkKeyFile Condition=”‘$(LinkKeyFile)’ == ””>%(Link.KeyFile)</LinkKeyFile>
    </PropertyGroup>
  6. Find the “LinkEmbedManifest” target (search for <Target Name=”LinkEmbedManifest”)
  7. Under the above target and in the task “<Link” perform the following steps.
  8. Change property  DelaySign
    1. From :       DelaySign   =”%(Link.DelaySign)”
    2. To :         DelaySign   =”$(LinkDelaySign)”
  9. Change property  KeyFile
    1. From :       KeyFile     =”%(Link.KeyFile)”
    2. To:         KeyFile     =”$(LinkKeyFile)”
  10. Repeat the steps 1 to 5 for “%ProgramFiles(x86)%MSBuildMicrosoft.Cppv4.0Platformsx64
  11. Note that this solution will move you back to the VS2010 RTM behavior and you would still need to use the original workaround to sign your assemblies using sn.exe in the custom build step.

Thank you for helping us improve quality of the product. We understand that this change has caused much pain to you and for which we are sorry. Meanwhile we are also looking at other avenues to provide you with this fix.

 

Thanks,
Amit