使用Visual Studio 2012时,SignTool.exe或“Windows Kits”目录的路径

时间:2012-12-29 13:13:07

标签: msbuild visual-studio-2012 signtool

使用Visual Studio 2012时,如何获得SignTool.exe的路径?

在Visual Studio 2010中,您可以使用

<Exec Command="&quot;$(FrameworkSDKDir)bin\signtool.exe&quot; sign /p ... />

$(FrameworkSDKDir)

的位置
"c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\"

但在Visual Studio 2012中,$(FrameworkSDKDir)

 "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\"

和SignTool在

 "c:\Program Files (x86)\Windows Kits\8.0\bin\x64\"

除了硬编码之外,有没有办法获取此目录的路径(我已尝试FrameworkSDKDirWindowsSDKDir,但两者都指向v8.0A目录。)

(我知道SignFile MSBuild任务,但我不能使用它,因为它不接受证书密码。)

7 个答案:

答案 0 :(得分:42)

我刚遇到同样的问题。从Visual Studio 2012命令提示符运行构建工作,但它在IDE中失败。寻找详细或诊断日志导致我What is the default location for MSBuild logs?,它告诉我Visual Studio无法提供我真正需要的诊断信息。

这是我最终要做的事情。

打开正常的命令提示符(不是Visual Studio命令提示符),并通过完全限定MSBuild(%SystemRoot%\ Microsoft.NET \ Framework \ v4.0.30319 \ MSBuild.exe)的路径来运行msbuild。这最终给了我在Visual Studio 2012中收到的相同错误消息(错误代码9009)。

然后,通过附加/ v:diag开关,使用“诊断”日志记录(显示所有属性和项目值)运行相同的构建。

从这个输出中,我了解到它确实有一些新属性可以用来获取signtool.exe的位置(摘录如下):

windir = C:\Windows
windows_tracing_flags = 3
windows_tracing_logfile = C:\BVTBin\Tests\installpackage\csilogfile.log
WindowsSDK80Path = C:\Program Files (x86)\Windows Kits\8.0\
WIX = C:\Program Files (x86)\WiX Toolset v3.7\

因此,我对此问题的解决方案是将以下内容添加到我的* .targets文件中:

<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>

希望这对你也有帮助。我包含了我如何达到这一点的序言,因为有其他可用的属性可能更适合您的目的。

答案 1 :(得分:15)

好的,因为这是谷歌第一次点击&#34;在buildserver&#34;上找不到SignTool.exe,我将为VisualStudio 2015和Windows 10 Enterprise 64bit添加附加信息。

我必须在VisualStudio安装程序中添加ClickOnce发布工具: Visual Studio 2015 Setup where you can add ClickOnce

在此之后,您可以在

中找到signtool.exe
  • c:\ Program Files(x86)\ Windows Kits \ 8.1 \ bin \ x64 \
  • c:\ Program Files(x86)\ Windows Kits \ 8.1 \ bin \ x86 \
  • c:\ Program Files(x86)\ Windows Kits \ 8.1 \ bin \ arm \

安装 Visual Studio 2017 后,可以在

中找到
  • C:\ Program Files(x86)\ Windows Kits \ 10 \ bin \ arm \ signtool.exe
  • C:\ Program Files(x86)\ Windows Kits \ 10 \ bin \ arm64 \ signtool.exe
  • C:\ Program Files(x86)\ Windows Kits \ 10 \ bin \ x64 \ signtool.exe
  • C:\ Program Files(x86)\ Windows Kits \ 10 \ bin \ x86 \ signtool.exe

使用 Visual Studio 2017 15.7.4 ,Path会根据您安装的所选Windows 10 Kit再次更改。

通过启动 Visual Studio 2017的开发人员命令提示符,您将获得路径通用 enter image description here

并输入  where signtool.exe

答案 2 :(得分:12)

以下是一种更通用的方法,可用于根据构建机器的特定配置查找和设置SignToolPath变量;通过阅读注册表:

<PropertyGroup>
    <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)' == ''">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath>
</PropertyGroup>

这假设$(Platform)解析为armx86x64之一。否则将$(Platform)宏替换为相应的目录。

编辑(2017.07.05):
这是一个更新的<PropertyGroup>,它遵循新的Windows 10工具包并强制($Platform)=='AnyCPU'x86

<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>

答案 3 :(得分:6)

Resolve-Path  "C:\Program Files*\Windows Kits\*\bin\*\signtool.exe"

<强>输出:

Path
----
C:\Program Files (x86)\Windows Kits\8.0\bin\x64\signtool.exe
C:\Program Files (x86)\Windows Kits\8.0\bin\x86\signtool.exe
C:\Program Files (x86)\Windows Kits\8.1\bin\arm\signtool.exe
C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe
C:\Program Files (x86)\Windows Kits\8.1\bin\x86\signtool.exe

答案 4 :(得分:3)

自从我今天(2020年7月20日)以来,所有以前的建议都失败了,尽管大多数建议过去都起作用,但我决定发布一种更全面的方法,该方法还可以解决Windows 10 SDK以后的位置,而仍然使用较旧的作为后备。

<PropertyGroup Label="UserDefinedVariables">

    <!-- Get Windows SDK root folder-->

    <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>

    <!-- Evaluates the most recent Windows SDK folder containing SignTool.exe -->

    <!-- add new versions here, duplicating following line -->
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.18362.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.18362.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.17763.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.17763.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.17134.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.17134.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.16299.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.16299.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.15063.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.15063.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And exists('$(WindowsKitsRoot)bin\10.0.14393.0\x64\Signtool.exe')">$(WindowsKitsRoot)bin\10.0.14393.0\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == '' And '$(Platform)' == 'AnyCPU' ">$(WindowsKitsRoot)bin\x64\</SignToolFolder>
    <SignToolFolder Condition="'$(SignToolFolder)' == ''">$(WindowsKitsRoot)bin\$(Platform)\</SignToolFolder>

    <!-- Now we should be able to calculate SignTool.exe fullpath -->

    <SignToolExe Condition=" '$(SignToolFolder)' != '' ">$(SignToolFolder)SignTool.exe</SignToolExe>

</PropertyGroup>


<!-- Finally, I would suggest you add the following lines to your project file because they will be quite usefull when things go wrong (and they will) -->

<!-- Send indivual compile bessages to MSBuild output so you check the value of each variable -->
<Target Name="ShowUserDefinedVariables" BeforeTargets="BeforeBuild">
    <Message Importance="High" Text="WindowsKitsRoot = $(WindowsKitsRoot)" />
    <Message Importance="High" Text="SignToolFolder = $(SignToolFolder)" />
    <Message Importance="High" Text="SignToolExe = $(SignToolExe)" />
</Target>

答案 5 :(得分:0)

我假设使用signtool对可执行文件或dll进行签名。在Visual Studio 2019中,有一个Developer命令行同时提供Developer Cmd和Developer Powershell。这两个选项都可以自动解决signtool,而无需担心当前的Windows SDK。

Screenshot of signtool being resolved

如果我们想从本地Powershell使用Developer Powershell,那么我们只需要为Developer Powershell导入模块即可。要导入模块,我们需要在本机Powershell中运行以下行:

&{Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"; Enter-VsDevShell 5ee267ff}

其中5ee267ff因每台计算机而异。您可以在“开发人员Powershell的属性”快捷方式中找到它。

一旦导入了模块,我们甚至可以从本机Powershell中解析signtool。最后,我们可以在项目的post build事件中添加一个脚本,以使该脚本导入Developer powershell,然后我们可以简单地使用signtool进行签名。

答案 6 :(得分:0)

我使用的这种方法仅依赖于标准构建事件:

powershell -Command "(Resolve-Path \"C:\Program Files (x86)\\Windows Kits\\10\\bin\\*\\x64\" | Select-Object -Last 1).Path" > stpath
set /p STPATH=<stpath
del stpath

"%STPATH%\signtool.exe" sign ..........

它会在安装新的 Windows SDK 并选择最新的 SDK 时处理新路径。