| Digitální podepisování PowerShell skriptů mě v poslední době docela otravuje, protože to zbytečně zdržuje. Kdykoliv uděláte nějakou změnu ve skriptu, musíte to nechat znovu podepsat. A PowerShell ISE má značný nedostatek v tom, že si nevšimne, když se soubory změní mimo prostředí. Takže je znovu nenahraje. Potřeboval jsem tedy primárně metodu, jak nechat pozavírat všechny soubory a znovu je otevřít. A vyklubalo se z toho toto:
Udělal jsem si tedy skript, který digitálně podepíše otevřené soubory (sign) rovnou z ISE. Řeší to několik problémů:
- musíte nejprve neuložené soubory uložit. Nechcete ukládat už uložené, protože by to zbytečně změnilo jejich časová razítka
- potom je musíte zavřít
- abych zbytečně nezavíral všechny soubory, zavírám jenom ty, jejichž digitální signatura (digital signature) není platná. A pouze .PS1 přípony, ono ISE má i pěkné obarvování XML, které rád používám
- podepsat ty soubory, co jste zavřeli
- otevřít je znovu do ISE
- a nastavit zpátky kurzor na pozici, kde byl před tím, než jsem je zavíral - jinak budete na začátku, což je dost otravné
Tady to je. Používám $psISE proměnnou. Funkci jsem si dal do PowerShell ISE profilu ($profile.AllUsersCurrentHost) a jede to jak po másle:
function global:Sign-ISE ([string] $signingCertSubjectMail = 'ondrej@sevecek.com')
{
[System.Security.Cryptography.X509Certificates.X509Certificate2] $signingCert = $null
$signingCert = dir Cert:\CurrentUser\My -CodeSigningCert | ? { $_.Subject -like "*E=$signingCertSubjectMail*" | Sort NotAfter | Select -Last 1 }
if ($signingCert -ne $null) {
$openFiles = $psISE.CurrentPowerShellTab | % { $_.Files }
foreach ($oneOpenFile in $openFiles) {
$oneFilePath = $oneOpenFile.FullPath
$oneFileLine = $oneOpenFile.Editor.CaretLine
$oneFileColumn = $oneOpenFile.Editor.CaretColumn
if (-not $oneOpenFile.IsSaved) {
[void] $oneOpenFile.Save()
}
if (([System.IO.Path]::GetExtension($oneFilePath) -eq '.ps1') -and ((Get-AuthenticodeSignature $oneFilePath).Status -ne 'Valid')) {
[void] $psISE.CurrentPowerShellTab.Files.Remove($oneOpenFile)
[void] (Set-AuthenticodeSignature $oneFilePath -Certificate $signingCert)
$reloadedFile = $psISE.CurrentPowerShellTab.Files.Add($oneFilePath)
$reloadedFile.Editor.SetCaretPosition($oneFileLine, $oneFileColumn)
}
}
} else {
throw 'Error: no signing certificate found'
}
}
Dá se dokonce přidat do menu Add-ons volba na tuto funkci. A to všechno i s asociací klávesové zkratky. Takto:
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Sign all", { Sign-ISE }, 'Ctrl+Alt+S')
|