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

Posted

技术标签:

【中文标题】使用 Visual Studio 2012 时 SignTool.exe 或“Windows Kits”目录的路径【英文标题】:Path to SignTool.exe or "Windows Kits" directory when using Visual Studio 2012 【发布时间】:2012-12-29 13:13:06 【问题描述】:

使用 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 任务,但我不能使用它,因为它不接受证书密码。)

【问题讨论】:

$(FrameworkSdkDir) 指向我机器上的 Windows 工具包。不要与 $(FrameworkSDKRoot) 混淆,您的问题中大小写错误。 MSBuild 属性在我的测试中不区分大小写。 FrameworkSDKRoot / FrameworkSdkDir 指向我项目中的同一个地方 - C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\ @Ryan 他们可能指向同一个地方,但这不是区分大小写的问题。 @EdwardThomson - 确定吗?在 MSBUILD 中获取您关心的任何属性,并使用 CraZY cAse 通过消息输出 - 它会起作用。试试看! @Ryan - 我是说FrameworkSdkDirFrameworkSdkRoot 大小写不同,但内容不同。 【参考方案1】:

我刚刚遇到了同样的问题。从 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>

希望这对您也有帮助。我在前言中包含了我是如何做到这一点的,因为还有其他可用的属性可能更适合您的目的。

【讨论】:

这是两年前的,但您能解释一下您是如何将它添加到您的目标中的吗?我的解决方法是添加到构建后事件: IF EXIST "C:\Program Files (x86)\Windows Kits\8.0\bin\x86\signtool.exe" "C:\Program Files (x86)\Windows Kits\8.0 \bin\x86\signtool.exe" 签名 /a /d "QA" $(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)\QA.exe【参考方案2】:

好的,因为这是 google 上第一次点击“SignTool.exe not found on buildserver”,我将添加 VisualStudio 2015 和 Windows 10 Enterprise 64bit 的附加信息。

我必须在 VisualStudio 设置中添加 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 中,路径会根据您安装的所选 Windows 10 工具包再次更改。

您将通过启动 Visual Studio 2017 开发人员命令提示符 获得通用路径

然后输入 where signtool.exe

【讨论】:

如果你已经安装了VS2015,你可以去控制面板->添加/删除程序->右键单击MS Visual Studio并选择更改重新运行这个安装向导并添加上面的选项【参考方案3】:

下面是一个更通用的方法,可以根据构建机器的具体配置来查找和设置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): 这是一个更新的&lt;PropertyGroup&gt;,它遵循新的 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>

【讨论】:

如果您使用AnyCPU 和特定平台进行编译,那么您将需要以下两个条件语句: &lt;SignToolPath Condition=" '$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' "&gt;$(WindowsKitsRoot)bin\x64\&lt;/SignToolPath&gt; &lt;SignToolPath Condition="'$(SignToolPath)' == ''"&gt;$(WindowsKitsRoot)bin\$(Platform)\&lt;/SignToolPath&gt; @Randy Walker, 靠近顶部,以便在需要它们的位置之前定义属性。如果已设置定义,Condition="'$(SignToolPath)'==''" 会阻止设置该属性。因此,操作系统中的环境变量将防止它在构建过程中被覆盖。 @RandyWalker,另外,在有问题的计算机上手动检查注册表项。我的 Windows 10 计算机使用以下注册表路径,而不是上面的那些:&lt;WindowsKitsRoot&gt;$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))&lt;/WindowsKitsRoot&gt; @RandyWalker,此外,还要检查构建环境中的其他.targets 文件是否调用GetRegistryValueFromView(),以防参数(例如RegistryView.Registry32)与上述相同。 【参考方案4】:
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

【讨论】:

【参考方案5】:

因为对我来说,今天(20/07/2020)之前的所有建议都失败了,尽管其中大多数在过去都有效,但我决定发布一个更全面的方法,该方法也解决了后来的 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>

【讨论】:

【参考方案6】:

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

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 安装并选择最新的,它将应对新的路径。

【讨论】:

【参考方案7】:

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

如果我们想从原生 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 的位置因每台机器而异。您可以在 Developer Powershell 快捷方式的属性中找到它。

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

【讨论】:

以上是关于使用 Visual Studio 2012 时 SignTool.exe 或“Windows Kits”目录的路径的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2010 的 Visual C++ 2012 运行时库先决条件

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

在 Visual Studio 2012 Ultimate 中的 Windows 中使用 OpenSSL 时出错

Visual Studio 2010 项目到 Visual Studio 2012

s-s-rS“报表服务器项目”不显示在 Visual Studio 2010 中

在 Visual Studio 2012 中安装包 Swashbuckle/swagger 时出错