Путь к каталогу SignTool.exe или Windows Kits при использовании Visual Studio 2012

Как получить путь к SignTool.exe при использовании Visual Studio 2012?

В 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\"

Есть ли способ получить путь к этому каталогу, кроме жесткого кодирования (я пробовал FrameworkSDKDir и WindowsSDKDir, но оба указывают на каталог v8.0A).

(Мне известно о SignFile MSBuild, но я не могу ее использовать, так как она не принимает пароли сертификатов.)


person Ryan    schedule 29.12.2012    source источник
comment
$(FrameworkSdkDir) указывает на комплекты Windows на моем компьютере. Не путайте с $(FrameworkSDKRoot), в вашем вопросе неправильная заглавная буква.   -  person Hans Passant    schedule 29.12.2012
comment
Свойства MSBuild нечувствительны к регистру из моего тестирования. FrameworkSDKRoot / FrameworkSdkDir указывают на одно и то же место в моем проекте - C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\   -  person Ryan    schedule 29.12.2012
comment
@ Райан, они могут указывать на одно и то же место, но дело не в чувствительности к регистру.   -  person Edward Thomson    schedule 29.12.2012
comment
@EdwardThomson - Уверен в этом? Возьмите любое имущество, которое вам нужно, в MSBUILD и выведите через сообщение с помощью CraZY cAse - оно сработает. Попробуй!   -  person Ryan    schedule 29.12.2012
comment
@Ryan - я говорю, что FrameworkSdkDir и FrameworkSdkRoot отличаются не регистром, а содержанием.   -  person Edward Thomson    schedule 29.12.2012


Ответы (7)


Я только что столкнулся с той же проблемой. Запуск сборки из командной строки Visual Studio 2012 работал, но в среде IDE происходил сбой. Поиск подробного или диагностического журнала привел меня к Каково расположение по умолчанию для Журналы MSBuild?, которые сказали мне, что Visual Studio не может предоставить диагностическую информацию, которая мне действительно нужна.

Вот что я наконец сделал, чтобы исправить это.

Откройте обычную командную строку (не командную строку Visual Studio) и запустите из нее msbuild, указав полный путь к MSBuild (%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe). Это, наконец, дало мне то же сообщение об ошибке (код ошибки 9009), которое я получал в Visual Studio 2012.

Затем запустите ту же сборку, используя «диагностическую» регистрацию (которая показывает все значения свойств и элементов), добавив переключатель /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>

Надеюсь, это поможет и вам. Я включил преамбулу того, как я пришел к этому моменту, потому что есть другие доступные свойства, которые могут лучше подходить для ваших целей.

person M. Shawn Dillon    schedule 02.01.2013
comment
Это было сделано два года назад, но можете ли вы объяснить, как вы добавили его в свои цели? Мой обходной путь состоял в том, чтобы добавить в событие после сборки: 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 sign /a /d QA $(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)\QA.exe - person Jaydel Gluckie; 13.10.2015

Хорошо, поскольку это был первый поиск в Google по запросу «SignTool.exe не найден на сервере сборки», я добавлю дополнительную информацию для VisualStudio 2015 и Windows 10 Enterprise 64bit.

Мне пришлось добавить средства публикации ClickOnce в программу установки VisualStudio: Установка Visual Studio 2015, в которую можно добавить 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

person gReX    schedule 03.12.2015
comment
И если вы уже установили VS2015, вы можете перейти в Панель управления -> Установка и удаление программ -> щелкните правой кнопкой мыши MS Visual Studio и выберите Изменить, чтобы повторно запустить этот мастер установки и добавить параметр выше. - person sfm; 15.07.2016

Ниже приведен более общий подход, который можно использовать для поиска и установки переменной 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) разрешается в одно из arm, x86 или 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>
person ergohack    schedule 08.12.2015
comment
При компиляции для AnyCPU вам все равно нужно указать один из arm, x86 или x64 для полного пути к исполняемому файлу signtool. Если вы когда-либо компилируете только с AnyCPU, замените макрос $(Platform) соответствующим явным фрагментом пути. - person ergohack; 24.01.2016
comment
Если вы компилируете с помощью AnyCPU и определенных платформ, вам понадобятся следующие два условных оператора: - person ergohack; 24.01.2016
comment
@ErgoHack это просто входит в файл csproj? Если да, то вниз или вверх? У меня все еще есть проблемы с поиском пути для signtool, даже когда командная строка VS на машине сборки может его найти. - person Randy Walker; 28.04.2017
comment
@ Рэнди Уокер, ‹PropertyGroup› идет вверху, так что свойства определяются до того, где они необходимы. Condition="'$(SignToolPath)'==''" предотвращает установку свойства, если определение уже установлено. Таким образом, переменная среды в ОС предотвратит переопределение этого во время сборки. - person ergohack; 29.04.2017
comment
@RandyWalker, также проверьте раздел реестра вручную на компьютере, где возникли проблемы. Вместо указанных выше, мой компьютер с Windows 10 использует следующий путь реестра: <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>. - person ergohack; 29.04.2017
comment
@RandyWalker, также проверьте другие файлы .targets в вашей среде сборки на наличие вызова GetRegistryValueFromView() в случае, если параметры (например, RegistryView.Registry32) такие же, как указано выше. - person ergohack; 29.04.2017
comment
@ErgoHack хорошо, по какой-то причине он волшебным образом перестал выдавать мне ошибку для signtool. Однако в файле журнала ничего не говорится о фактической подписи манифеста, и я продолжаю получать ту же ошибку. Идентификатор развертывания не соответствует подписке. Любые мысли о том, как можно решить проблему? Рад опубликовать новый выпуск, чтобы вы могли получить кредит. Черт возьми, я мог бы даже нанять вас, если вы думаете, что можете решить проблему. Мои последние разработчики работали с TFS, и я перенес код на GitHub. - person Randy Walker; 07.05.2017
comment
@ Рэнди, похоже, он не запускается из сценариев сборки. Вы можете использовать элемент ‹message ...› (см. stackoverflow.com/questions/4771913/ ), чтобы получить представление о том, какие переменные установлены и какие строки выполняются. - person ergohack; 09.05.2017

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
person hdev    schedule 28.06.2017

Поскольку для меня сегодня (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>
person Julio Nobre    schedule 20.07.2020

Я предполагаю, что signtool используется для подписи исполняемых файлов или DLL. В Visual Studio 2019 есть командная строка разработчика, которая предлагает как Developer Cmd, так и Developer Powershell. Оба эти варианта могут автоматически разрешать средство подписи, не беспокоясь о текущем Windows SDK.

Скриншот решения signtool

Если мы хотим использовать Developer Powershell из собственного 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.

После того, как модуль импортирован, мы можем разрешить signtool даже из родной оболочки powershell. В конце мы можем добавить сценарий в событие после сборки проекта, чтобы этот сценарий импортировал PowerShell разработчика, а затем мы могли просто использовать инструмент подписи для подписи.

person Navjot Singh    schedule 12.08.2020

Этот подход, который я использую, просто опирается на стандартные события сборки:

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 и выберет самый последний.

person PhonicUK    schedule 15.01.2021