Разочарование с PowerShell и Signtool: по пути к решению
Если вы когда-либо сталкивались с проблемами при использовании PowerShell для автоматизации задач, вы знаете, как это может вызывать разочарование. Недавно я провел несколько часов, пытаясь решить проблему, связанную с использованием команды signtool
в Windows с помощью PowerShell. Mоя цель состояла в том, чтобы создать удобный скрипт для подписи файлов, но результаты оказались далеко не идеальными. Давайте рассмотрим, что пошло не так и как я намеревался это исправить.
Проблемы с использованием Start-Process
Первоначально я собирался использовать команду Start-Process
, поскольку это распространенная практика для запуска каких-либо приложений. Однако я быстро обнаружил, что у нее есть свои недостатки. Основная проблема заключалась в том, что Start-Process
выполняет команды асинхронно и имеет сложности с передачей кода состояния. Это означало, что следить за результатами выполнения было невозможно, что создавало дополнительные трудности.
Особенности интерфейса командной строки signtool
При работе с signtool
оказалось, что интерфейс командной строки имеет свои особенности. Среди наиболее важных моментов:
- Ключи и значения должны передаваться как отдельные аргументы. Если они сгруппированы в одну строку, интерпретатор будет воспринимать это как один переключатель, а не как пару ключ-значение.
- Ключи должны начинаться с
/
, а не с-
. - Пары ключ-значение не могут использовать двоеточие (
:
) для разделения.
Эти ограничения заставили меня пересмотреть подход к созданию аргументов.
Предоставление аргументов только при необходимости
Одной из ключевых задач при разработке моего скрипта было отправлять дополнительные аргументы для ключевых значений только в том случае, если они действительно присутствуют. Например, переменную $description
следовало передавать только если она была задана. Исходя из этого, был создан небольшой сценарий, который принимает всего два аргумента: sign
и все дополнительные $arguments
.
Ниже приведен пример кода:
param(
[Parameter(Mandatory=$true)][string]$file,
[string]$description,
[string]$expanded_description_uri
)
$arguments = "/fd sha256 /td sha256 /tr http://timestamp.digicert.com /a ${file}"
if (-not [string]::IsNullOrEmpty($description)) { $arguments = "/d `"$description`" " + $arguments }
if (-not [string]::IsNullOrEmpty($expanded_description_uri)) { $arguments = "/du `"$expanded_description_uri`" " + $arguments }
& 'C:\Program Files (x86)\Windows Kits/10/bin/10.0.26100.0/x64/signtool.exe' sign $arguments
exit $LASTEXITCODE
Разделение аргументов для корректной передачи
Далее в процессе разработки я столкнулся с необходимостью разделить аргументы правильно. Я использовал команду -Split
, которая показала себя надежной:
$arguments = -Split $arguments
& 'C:\Program Files (x86)\Windows Kits/10/bin/10.0.26100.0/x64/signtool.exe' sign $arguments
Это решение позволило избежать путаницы с разделением аргументов и гарантировало, что они были переданы корректно без необходимости использования неоднозначного синтаксиса.
Заключение: освободите себя от разочарования
Эта история о моих попытках работы с signtool
и PowerShell подчеркивает важность понимания тонкостей интерфейсов командной строки и синтаксиса. Важно помнить, что изучение и понимание особенностей систем, с которыми вы работаете, может значительно упростить жизнь. После всех этих трудностей я наконец достиг желаемого результата, и теперь я мог бы сосредоточиться на более продуктивных задачах. Если вы когда-либо столкнетесь с подобными проблемами, надеюсь, что этот опыт поможет вам найти эффективное решение.