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 "$(SNToolPath)".
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=""$(SNToolPath)" -Rca "@(MyAssembly)" "$(KeyContainerName)" " />
<Exec Condition=" '$(KeyContainerName)' == '' "
Command=""$(SlpsSdkProtectSnTool)" -Ra "@(MyAssembly)" "$(KeyOriginatorFile)" " />