Cannot find sn.exe to sign Assembly

I looked into C:\Program Files\Microsoft.NET and I can't see any SN.exe file.

I have .NET 3.5 runtime installed; isn't that enough ?


You need to install the Windows SDK 6.0a, not just the runtime.

If you've installed VS2008, you'll find it's already installed, and sn.exe will be here:

C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\sn.exe

Otherwise, if you don't have VS2008 installed, you can download the SDK individually here.

The file sn.exe is not available in the SDK. The current version of the SDK is 6.1, perhaps they removed sn.exe in this release.


  • open command prompt
  • type cd \
  • type dir /s sn.exe
  • you will get output something like

    Volume in drive C has no label.

    Volume Serial Number is XXXX-XXXX.

Directory of C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin

11/07/2007  12:01 PM            95,728 sn.exe
              1 File(s)         95,728 bytes

You found the directory :)
if not, there is no sn.exe in your system. Install SDK then.


I'm sure you have your reasons -- and there are definitely plenty cases where SN.exe is unavoidable and/or appropriate (Delay Signing for one). (And I've +1'd the Q and the Accepted A and am not disputing their merit in any way so please disregard this if it doesn't apply in your case)

Note that SN.exe is rarely needed in practice - the wiring in Microft.<lang>.targets that drive the compilers [and AL.exe etc.] all [effectively] take the SignAssembly flag in the .proj file into account and conditionally pass in the key to the compiler(s) etc. so it can do all the work in a single touch of the assembly inline (mainly for perf reasons).

This logic also deals with the distinction between .snk and .pfx keys (which are password protected and get secreted into a Key Container). Depending on which form, there is then either a KeyContainerName or KeyOriginatorFile property resolved by Microsoft.Common.targets in the Runtime directory - Search for ResolveKeySource.

If the reason you need to do a SN is because you've just rewritten an assembly, the same pattern should generally hold, i.e. Mono.Cecil and tools a la PostSharp (I assume, not confirmed) generally also take the same arguments and/or can be made to do the signing inline.


Microsoft.Common.targets excerpt

<Target Name="ResolveKeySource" 
  Condition="$(SignManifests) == 'true' or $(SignAssembly) == 'true'">

  <ResolveKeySource ...
    KeyFile="$(AssemblyOriginatorKeyFile)"
    CertificateFile="$(ManifestKeyFile)"
    SuppressAutoClosePasswordPrompt="$(BuildingInsideVisualStudio)">
      <Output TaskParameter="ResolvedKeyFile" PropertyName="KeyOriginatorFile" ..."/>
      <Output TaskParameter="ResolvedKeyContainer" PropertyName="KeyContainerName" ... "/>

Microsoft.CSharp.targets excerpt

    <Csc  ...
          KeyContainer="$(KeyContainerName)"
          KeyFile="$(KeyOriginatorFile)" />

For completeness, here's how to programmatically infer the SDK path relevant to the target you are compiling (tested on 4.0 but same approach is possible all the way back to 2.0, i.e. Microsoft.Common.targets has processed this data for some time):

<Target Name="ResolveSNToolPath" Condition=" 'true' == '$(SignAssembly)' ">
    <PropertyGroup>
      <_SdkToolsBinDir Condition=" '' == '$(_SdkToolsBinDir)' ">$(TargetFrameworkSDKToolsDirectory)</_SdkToolsBinDir>
      <SNToolPath Condition=" '' == '$(SNToolPath)' ">$(_SdkToolsBinDir)SN.exe</SNToolPath>
    </PropertyGroup>
    <Error Condition=" 'true' == '$(SignAssembly)' AND !EXISTS( '$(SNToolPath)' )"
      Text="In order to resign the assembly, this package requires access to the SN.EXE tool from the Windows Platform SDK, which was not found.

The location derived was &quot;$(SNToolPath)&quot;.

Please either:
1) supply a correct path to your SDK Tools bin directory containing SN.EXE by setting %24(_SdkToolsBinDir) or %24(TargetFrameworkSDKToolsDirectory)
OR
2) supply a correct complete path to your SN.EXE signing tool by setting %24(SNToolPath)" />
  </Target>

For total completeness, here's how you would leverage the outputs of this process to run SN.exe

<Target Name="ResignMyAssembly" Condition="$(SignAssembly) == 'true'">
  <Exec Condition=" '$(KeyContainerName)' != '' " 
    Command="&quot;$(SNToolPath)&quot; -Rca &quot;@(MyAssembly)&quot; &quot;$(KeyContainerName)&quot; " />
  <Exec Condition=" '$(KeyContainerName)' == '' " 
    Command="&quot;$(SlpsSdkProtectSnTool)&quot; -Ra &quot;@(MyAssembly)&quot; &quot;$(KeyOriginatorFile)&quot; " />