5

I've taken on project based on Visual Studio 2012. There the path to signtool.exe is found the following way:

<SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x86\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='x86' ">$(WindowsSDK80Path)bin\x86\signtool.exe</SignToolPath>
<SignToolPath Condition=" Exists('$(WindowsSDK80Path)bin\x64\signtool.exe') and '$(SignToolPath)'=='' and '$(PROCESSOR_ARCHITECTURE)'=='AMD64' ">$(WindowsSDK80Path)bin\x64\signtool.exe</SignToolPath>

Now i want to port the project to Visual Studio 2017. With this installed this way to get the path is no longer working because of missing Windows SDK 8.

I've installed the Click Once component and the Windows 10 SDK. Therefore signtool.exe is available.

Can someone tell me how to find the path with Visual Studio 2017?

Action Heinz
  • 722
  • 10
  • 23

4 Answers4

4

Can someone tell me how to find the path with Visual Studio 2017?

You could find and set the SignToolPath variable from the the registry based on the configuration:

<PropertyGroup>
  <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
  <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot81', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
  <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
  <SignToolPath Condition=" '$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' ">$(WindowsKitsRoot)bin\x86\</SignToolPath>
  <SignToolPath Condition="'$(SignToolPath)' == ''">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath>
</PropertyGroup>

We could set this property into our project file or .target file then import it to the project file.

Alternatively, you could set environment variable to SignToolPath, the global system path (via ControlPanel->System->Advanced system settings->Environment variables):

C:\Program Files (x86)\Windows Kits\10\bin\x86

Hope this helps.

Leo Liu
  • 71,098
  • 10
  • 114
  • 135
2

based on Leo's response, here is my updated PropertyGroup for Windows Kit 10. It is not thoroughly tested but it works on my machine ;-)

  <PropertyGroup>
    <!-- Windows Kits 10 -->
    <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <SignToolPath Condition="'$(WindowsKitsRoot)' != '' And '$(SignToolPath)' == '' And exists('$(WindowsKitsRoot)bin\10.0.18362.0\')">$(WindowsKitsRoot)bin\10.0.18362.0\$(Platform)\</SignToolPath>
    <SignToolPath Condition="'$(WindowsKitsRoot)' != '' And '$(SignToolPath)' == '' And exists('$(WindowsKitsRoot)bin\10.0.18362.0\')">$(WindowsKitsRoot)bin\10.0.17763.0\$(Platform)\</SignToolPath>
    <SignToolPath Condition="'$(WindowsKitsRoot)' != '' And '$(SignToolPath)' == '' And exists('$(WindowsKitsRoot)bin\10.0.18362.0\')">$(WindowsKitsRoot)bin\10.0.17134.0\$(Platform)\</SignToolPath>
    <SignToolPath Condition="'$(WindowsKitsRoot)' != '' And '$(SignToolPath)' == '' And exists('$(WindowsKitsRoot)bin\10.0.18362.0\')">$(WindowsKitsRoot)bin\10.0.16299.0\$(Platform)\</SignToolPath>

    <!-- Windows Kits 8 and older -->
    <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot81', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <SignToolPath Condition=" '$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' ">$(WindowsKitsRoot)bin\x86\</SignToolPath>
    <SignToolPath Condition="'$(SignToolPath)' == ''">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath>
  </PropertyGroup>
invalidusername
  • 912
  • 9
  • 26
1

Based on Leo's response, that independent on Windows Kits version, but it uses Target. $(SignToolPath) will contain path to signtool.exe.

Main idea use standard sort order in MSBuild and set to property SignToolPath last item of itemgroup SignToolPaths

<Target Name="ResolveSignToolPath" BeforeTargets="SignFile">
    <ItemGroup>
        <KitsRegKeys Include="KitsRoot" />
        <KitsRegKeys Include="KitsRoot81" />
        <KitsRegKeys Include="KitsRoot10" />
        <KitsRegKeyValues Include="@(KitsRegKeys)">
            <Value>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', '%(KitsRegKeys.Identity)', null, RegistryView.Registry32, RegistryView.Default))</Value>
        </KitsRegKeyValues>
    </ItemGroup>
    <PropertyGroup>
        <WindowsKitsRoot>%(KitsRegKeyValues.Value)</WindowsKitsRoot>
        <SignToolPlatform Condition="'$(SignToolPlatform)'=='' And '$(Platform)'!='AnyCPU'">$(Platform)</SignToolPlatform>
        <SignToolPlatform Condition="'$(SignToolPlatform)'==''">x86</SignToolPlatform>
    </PropertyGroup>
    <ItemGroup>         
        <SignToolPaths Include="$(WindowsKitsRoot)bin\**\$(SignToolPlatform)\signtool.exe"/>
    </ItemGroup>
    <PropertyGroup>
        <SignToolPath>%(SignToolPaths.Identity)</SignToolPath>
    </PropertyGroup>        
    <Error Condition="'$(SignToolPath)'=='' Or !Exists('$(SignToolPath)')"
       Text="In order to sign file, this package requires access to the signtool.exe tool from the Windows Kits, which was not found. Please either: 1) Supply a correct path to your Windows Kits bin directory containing signtool.exe by setting %24(SignToolPath) OR 2) Install Windows Kits" />
    <!-- <Message Text="Signing $(SignToolPath)" Importance="high" />        -->
</Target>
0

I recently found a registry key which contains the needed path for the signtool.exe.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots] "WdkBinRootVersioned" = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\"

So this works for me:

<PropertyGroup>
    <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'WdkBinRootVersioned', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <SignToolPath Condition="'$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU'">$(WindowsKitsRoot)x86\</SignToolPath>
    <SignToolPath Condition="'$(SignToolPath)' == ''">$(WindowsKitsRoot)$(Platform)\</SignToolPath>
</PropertyGroup>
Sebastian
  • 315
  • 3
  • 10