45

使用 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\"

除了硬编码(我试过FrameworkSDKDirand WindowsSDKDir,但都指向 v8.0A 目录)之外,有没有办法获得这个目录的路径。

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

4

7 回答 7

44

我刚刚遇到了同样的问题。从 Visual Studio 2012 命令提示符运行构建工作,但它在 IDE 中失败。寻找详细或诊断日志导致我到MSBuild 日志的默认位置是什么?,这告诉我 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>

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

于 2013-01-02T09:42:40.770 回答
19

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

我必须在 VisualStudio 设置中添加 ClickOnce 发布工具: Visual Studio 2015 安装程序,您可以在其中添加 ClickOnce

在此之后,您会在以下位置找到 signtool.exe

  • c:\Program Files (x86)\Windows 工具包\8.1\bin\ x64 \
  • c:\Program Files (x86)\Windows 工具包\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

于 2015-12-03T08:38:16.737 回答
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)解析为armx86或之一x64。否则用适当的目录替换$(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>
于 2015-12-08T19:34:25.307 回答
7
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
于 2017-06-28T08:31:16.780 回答
3

因为对我来说,今天(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>
于 2020-07-20T22:03:29.913 回答
1

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

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

于 2021-01-15T12:07:12.963 回答
0

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

正在解析的signtool截图

如果我们想从本机 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 进行签名。

于 2020-08-12T07:26:06.453 回答