Powershell 7 RC2

Eelmine nädal toimus Powershell Community Call ja selle käigus teatati, et tuleb välja Powershell 7 Release Candidate 2. Ja sellega seoses nihutati lõpliku versiooni tähtaeg veebruarisse.

Powershell Release Candidate (sealhulgas ka RC2) on toetatud versioon, mis tähendab et probleemide korral saab pöörduda Microsofti toe poole.

Microsoft soovitab tungivalt juba praegu proovida, et kas kõik Windows Powershelli all töötav jookseb ka Powershell 7 all. Ja kui on midagi, mis ei lase uue versiooni peale üle minna, siis peaks sellest kindlasti teatama.

Praeguseks on kindel et üleminek tuleb korraldada käsitsi. Powershell 7 käivituv programm on pwsh.exe, mitte powershell.exe, seega tuleb kõik automaatikad üle vaadata ja ära muuta. Lisaks tuleb arvestada, et kuna .NET Core on siiski natuke erinev .NET Framework’ist, siis ei pruugi kõik asjad tööle jääda.

Samuti on soovitav viia Powershelli kaugühendused WinRM protokollilt üle SSH protokollile. See omakorda vajab, et masinatesse lisataks OpenSSH või mõni muu SSH protokolli oskav komponent. Windows 10 1809/Server 2019-ga tuleb OpenSSH kaasa, aga vanematele OS-idele tuleb see eraldi alla laadida ja käsitsi lisada. Ja häälestada tuleb SSH Serverit ikka, ning esialgu tuleb seda teha suht käsitsi.

Powershell 7 lisamine Windowsile jääb esialgu ka suhteliselt käsitööks. On olemas .MSI või .MSIX pakk ja miskis tulevikus ilmub Powershell 7 ka Microsoft Store keskkonda. Versioon 7.1 ajaks saab ehk midagi automaatsemat, aga kindel veel ei ole.

Muuhulgas oli Community Call’i ajal juttu ka Powershelli järgmisest versioonist. See on siis versioon 7.1 ja see saab seotud .NET 5 valmis saamise ajaga (praegu plaanis November 2020). Ja edaspidi saavadki Powershelli uued versioonid välja tulema koos uue .NET versioonga (ehk siis korra aastas) ning nende toe tingimused vastavad .NET versiooni toele.

Powershell 7 tulekul

Eile sai valmis Powershell 7 Preview 4, sellega seoses võiks sellest natke pikemalt rääkida. Seda enam et selle versiooniga on plaanis mitmed muutused.

Üks suuremaid (ja oodatumaid) muutusi on see, et selle versiooniga on plaanis parandada Powershelli kokkusobivust Windowsiga. Tundub natuke imelik sedasi rääkida, ent Powershell Core (6.x) peamine sihtgrupp oli pigem teised toetatud platvormid. Ja seetõttu ei töödanud paljud Windows Powershellis töötavad moodulid Powershell Core keskkonnas.

Powershell 7 kasutab .NET Core 3.1 versiooni, mis toob tagasi paljud funktsioonid, mis .NET Core 2.0-s olid puudu. See paneb paljud Powershell Core keskkonnas mitte töötanud moodulid loodetavasti jälle tööle. Lisaks võib veel mainida et Server 2019/Windows 10 v1809 väljatulekuga käidi üle OS-iga kaasatulevad moodulid ja paljud neist pandi Powershell Core sees tööle.

Teine suur asi on see, et uus versiooni on planeeritud asendama Windows Powershelli. Seni on Powershell Core olnud eraldi paralleelne versioon, mis ei asenda, vaid täiendab Windows Powershelli. V7 on mõeldud v5.1 asendama, nii et seni Windows Powershelli platvormile jäänud kasutajad saavad ka nautida vahepeal toimunud uuendusi ja parandusi. See on muuhulgas ka üks põhjusi, miks uus versioon on v7, mitte v6.3.

Kevadel, kui v7 Preview 1 välja kuulutati, siis teatati ka seda, et see saab olema esimene Long Term Servicing versioon pärast v6 väljatulekut. Nimelt on v7 toetatud niikaua, kuni on toetatud .NET Core 3.1. Seniste Powershell Core versioonide tugi on järginud Modern Lifecycle Support poliitikat. Selle järgi tuleb v6.2.2 uuendada uueks v6.2.3-ks 30 päeva jooksul pärast avaldamist, et tugi kehtiks. Sama loogika järgi on toetatud ka v6.1.6, kuigi ametlikult vaid septembri lõpuni (6 kuud v6.2 väljalaskest).

Funktsionaalsuse poole pealt on tegemist pigem evolutsiooni, kui revolutsiooniga. On hulk asju, mis kunagi välja lubati aga mis pole veel valmis saanud. Siis on mõned uued eksperimentaalsed funktsioonid, nagu näiteks PSForEachObjectParallel või PSTernaryOperator. Ülejäänud nipet-näpet on mõistlikum ise muudatuste logist järele vaadata.

Powershell spikri kirjutamine

Powershelli spikri kasutamisest sai mõnda aega tagasi kirjutatud. Nüüd vaataks, kuidas selle spikri sisu loomise ja muutmisega on.

Powershelli spikri süsteem kasutab info hoidmiseks XML-vormingut, mis on isegi dokumenteeritud. Ent sellega ümberkäimine on suhteliselt ebamugav (isegi kui omada selleks sobivaid tööriistu) ning see peab olema samas masinas, kus spikrit lugeda tahetakse. Seetõttu on spikri sisu dünaamiline muutmine/uuendamine natuke keeruline.

Teiseks on skriptidele spikri kirjutamisel võimalik kasutada XML-vormingu asemel hoopis skripti sisse käivat kommentaaripõhist spikrit. Muidugi saab kommentaaripõhisest spikrist alati viidata ka välisele (XML-põhisele) spikrile.

Kolmandaks on moodulite spikris niinimetatud about-teemad, mida hoitakse tavaliste tekstifailide kujul.

Powershell 3.0 lisas spikrisüsteemile veel Online-spikri ja spikri värskendamise toe. Aga see teeb elu veelgi ebamugavamaks, kuna nüüd tuleb hallata nelja erinevat vormingut:

  1. tekstifailid
  2. XML-vormingus spikker
  3. veebisait online-spikriga
  4. veebisait, kust saab muudetud spikri sisu alla laadida (ja sellega koos alla laetava spikri fail).

Õnneks paistab tunneli otsast valgust. Powershelli moodul platyPS pakub võimalust tuua kõik ülalmainitud spikri vormingud kokku ühe ja sama allika peale ning muuta spikri sisu samast allikast kättesaadavaks kõigis ülaltoodud vormingutes.

platyPS pakub võimalust hoida spikri sisu Markdown-vormingus, mis on inimloetav ja lihtsasti muudetav mistahes tekstiredaktoriga. Paljud veebisaidid oskavad Markdown-vormingut automaatselt näidata HTMLi kujul. Seega on Online-spikker sellega valmis.

Järgmine samm on XML-vorming. platyPS sisaldab käsku New-ExternalHelp, millega saab Markdown-spikri teemad teisendada XML-vormingusse. Ja ühtlasi pakkida ka uuendatava spikri failiks, mida saab veebisaiti üles laadida.

Kui Sa leiad, et Markdown on koodist eraldi ning jääb seetõttu tähelepanuta, siis oskab platyPS teisendada kommentaaripõhise spikri Markdown-vormingusse. Nii et siis tuleb lihtsalt aeg-ajalt värskendada oma Markdown spikri teemasid ja need seejärel kättesaadavaks teha. Kommentaarid ise on alati koodiga koos ja seega kohe kättesaadavad koodi arendajale.

Powershell 6 plaanib kogu spikrisüsteemi viia XML-vormingult üle Markdown vormingusse. Juba praegu on Powershell 6.1-s lisatud käsk ConvertFrom-Markdown, mis loeb Markdown-vormingut ja muudab selle Powershelli käsurealt kasutatavaks.

Suuremates projektides tekib vajadus hoida dokumentatsioon (ja spikker) koodist lahus, kuna dokumenteerimisega võivad tegeleda teised inimesed. Ka sellisel juhul on Markdown-vorming hea. Ilus näide selle kohta on Microsofti dokumentatsiooni sait docs.microsoft.com. Kogu selle sisu on tegelikult Github’is üleval ja kaastööks kättesaadav.

Windows Server 2019

Hiljuti kuulutas Microsoft, et selle aasta teises pooles tuleb välja Windows Server 2019.  Juba praegu saavad Windows Insider programmiga liitunud alla laadida Server 2019 eelvaate versioone.

Windows Server 2019 on järgmine Long-Term Servicing Channel väljalase.  See tähendab et see sobib muuhulgas Exchange, Sharepointi või SQL Serveri jooksutamiseks ning kaugtöölaua serveriks.

Muuhulgas on lubatud, et Server Core paigaldus peaks kuni 3 korda väiksemaks minema.  Siis on hea hulgi konteinereid luua.

Lubatud on veel mitmeid asju, nagu näiteks Windows Subsystem on Linux ja Windows Admin Center (endine Project Honolulu), samuti nagu juba Windows 10 peal olemasolevad Windows Defender Advanced Threat Protection ning Windows Defender ATP Exploit Guard.

Võta endale aega, tõmba eelvaated alla, paigalda ning proovi.  Ja kui leiad midagi parandada, siis saada kindlasti tagasisidet.

Powershell Direct

Windows 10 ja Server 2016 võimaldavad luua PowerShelli sessiooni Hyper-V host masina pealt otse virtuaalmasinasse.  See funktsionaalsus kannab nime PowerShell Direct ja on isegi dokumenteeritud.

Dokumentatsioonist ülalmainitud lehel on välja jäänud see pisiasi, et virtuaalmasina häälestuse versioon peab olema 6.2 või värskem.  Ilma selleta ei õnnestu virtuaalmasinaga ühendust saada.  Selle asemel tuleb veateade:

An Error has occured which Windows PowerShell cannot handle. A remote session might have ended.  

Põnev on see, et nii saab ühendust isegi Windows 10 virtuaalmasinaga, milles on Powershell Remoting ikka veel välja lülitatud.

PowerShelli tulevikust

Eelmine kord rääkisime sellest, kuidas tuvastada keskkonda, milles skript jookseb.  Sealt jäi välja üks pisiasi: kuidas tuvastada Nano Server või Server Core keskkonda.

Server Core keskkonnaga on lihtne, seal on meil tavaline Powerhsell keskkond ja OS funktsioonidega kaasatulevad haldusmoodulid.  Vajadusel saab seda kontrollida:

$regPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels\'

#Requires -Version 5.0
Get-ItemPropertyValue -Path $regPath -Name ServerCore

#Requires -Version 2.0
$RegKey = Get-ItemProperty -Path $regPath -EA SilentlyContinue
if ($RegKey."Server-Gui-Shell") {
  "Server with Desktop Experience"
} elseif ($RegKey.ServerCore) {
  "Server Core"
} elseif ($RegKey.NanoServer) {
  "Nano Server"
} else {
  "Not a Server OS"
}

Nano Server keskkonnaga on natuke raskem.  Nimelt on seal ruumi kokkuhoiuks OS funktsionaalsust vähendatud, sealhulgas .Net Framework on seal .Net Core, mitte täielik .Net Framework.  Ja kuna PowerShell sõltub .Net keskkonnast, siis on ka PowerShelli funktsionaalsus vähendatud.  Lisaks on puudu terve hunnik haldusmooduleid, mis tavaliselt olemas on.  Vähendatud funktsionaalsusega keskkond on tuntud kui PowerShell Core Edition:

#Requires -Version 5.1
$PSVersionTable.PSEdition

if ($PSVersionTable.PSEdition -like 'Core') {
  Write-Verbose 'Powershell Core'
} else {
  Write-Verbose 'Windows Powershell'
}

Natuke segadust võib tekitada see, et PowerShell v6 ajal pandi sellele nimeks PowerShell Core. Ja v7 nimetati jälle ümber (seekord lihtsalt PowerShell).

Skriptile võib lisada kontrolli, et vältida skripti käivitumist vales keskkonnas:

#Requires -Version 5.1
#Requires -PSEdition Core

Samuti on võimalik mooduli lisamisel/kasutamisel kontrollida, et see toetab keskkonda, kus teda kavatsetakse kasutada:

Find-Module -Tag PSEdition_Core

Get-Module -ListAvailable |
  Where-Object CompatiblePSEditions -Contains "Core"

Get-Module -ListAvailable | Where-Object {$_.CompatiblePSEditions}

Esialgu on moodulid ilma vajaliku infota manifestis, ent Windows 10 v1809/Server 2019 keskkonnas on OS-iga kaasatulevad moodulid juba ilusti märgistatud.  PowerShell Gallery moodulid on ka juba sildistatud või siis ei ole mooduli autor pidanud seda vajalikuks.

Pisike probleem selle märgistamisega on selles, et kui moodul peaks töötama ka varasemates PowerShelli versioonides, kui 5.1, siis ei saa CompatiblePSEditons tunnust lisada. Varasemad versioonid leiavad selle peale, et moodul on vigane ning ei lae seda. See on ka põhjus, miks Powershell Gallery soovitab lisada hoopis väljaande ja OS-põhised sildid. Nendesamade siltide järgi saab ka lokaalseid mooduleid filtreerida:

Get-Module -ListAvailable | Where-Object Tags -Contains 'Linux'

Get-Module -ListAvailable |
    Where-Object Tags -Contains 'PSEdition_Core'

Arvestades, et PowerShell 6 (ja 7) on juba olemas, tasub tähele panna:

  • Windows PowerShell 5.1 on viimane omast klassist ja seda edasi ei arendata.
    • Kõik Windows PowerShelliga seotud probleemid/ettepanekud tuleb raporteerida UserVoice saidis.  Vigade parandusi väidetavasti veel tehakse.
  • PowerShell on nüüd avatud lähtekoodiga projekt.  Seda ei panda Windowsiga kaasa, kuna seda arendatakse korraga mitmele platvormile: Windows, Linux, macOS.
  • PowerShell 6+ paigaldatakse Windows PowerShelli kõrvale ja see tuleb käivitada kui pwsh.exe
  • Kõik PowerShell 6/7-ga seotud probeemid/ettepanekud tuleb esitada Github saidis.
  • PowerShell 6+ ei sisalda enam järgmiseid asju:
    • Powershell ISE liides.  Arendustiim pakub alternatiivina kasutada Visual Studio Code redaktorit, mille Powershelli plugin on võimekam kui ISE.
    • Töövoogude (workflow) mootor.
  • Desired State Configuration saab samuti ümber kirjutatud .Net Core baasil (kunagi ehk).
  • PowerShell 2.0 režiimi ei ole enam v6+ sees. Samuti soovitatakse sellest v5+ peal lahti saada.

PowerShell 6+ kasutamisel on vaja tuvastada ka OS, mille peal joostakse.  Kuna CimCmdlets moodul pole veel komplektis, kui OS ei ole Windows, siis tuleb OS tuvastada teist moodi:

#Requires -Version 5.1
$PSVersionTable.PSEdition

#Requires -PSEdition Core
$PSVersionTable.OS

if ($PSVersionTable.PSEdition -like 'Core' ) {
    'PowerShell Core, OS: {0}' -f $PSVersionTable.OS
} else {
  "Windows PowerShell"
}

#Requires -Version 6
$IsWindows
$IsMacOs
$IsLinux

Kokkuvõtteks võib öelda, et tasub kõik oma skriptid/moodulid üle vaadata ning lisada vajalikud kontrollid, et vales keskkonnas oma töö asjaliku veateatega lõpetada. Ja lisada neile ka vajalikud sildid, et inimesed neid asjata alla ei tõmbaks.

Mis keskkonnas mu skript jookseb

Iga Windowsi süsteemiülem peab oskama PowerShelli kasutada.  Kui ta seda ei oska, siis ei saa ta ennast Windowsi süsteemiülemaks nimetada.  Ja vähehaaval nad seda ka õpivad (kui nad juba ei oska).

Kõik on väga tore, kuni me teame, millises masinas me oma asju jooksutame.  Aga kui me oleme jõudnud juba sinnamaale, et koodi jooksutatakse automaatselt, siis läheb elu keerulisemaks.  Nimelt tuleb siis hakata tuvastama, et mis keskkonnas kood parasjagu jookseb.  Sest kui seda mitte teha, siis võib kood mitte töötada.

Üks esimesi asju mida tuvastada on see, et kas meil on ka süsteemiülema õigused.  Seda on lihtsaim teha, kui luua omale abistav funktsioon:

function Test-IsAdmin {
  $AdminRole = [Security.Principal.WindowsBuiltinRole]::Administrator
  $CurrentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
  $CurrentUser = [Security.Principal.WindowsPrincipal] $CurrentIdentity
  $CurrentUser.IsInRole($AdminRole)
}

Ja siis saab seda kasutada.  Alates Powershelli versioonist 4.0 on ka teine viis (täpsem info Powershelli spikris):

if (-not (Test-IsAdmin)) {
  throw "Süsteemiülema õigused vajalikud, katkestan"
}

#Requires -RunAsAdministrator

Kui süsteemiülema õigused on puudu, siis saab neid vajadusel omandada.  Sellest sai kirjutatud varem.

Tasub tähele panna ka seda, et #Requires kontrollid töötavad ainult salvestatud skripti sees ning neid kontrollitakse juba skripti laadimisel.  See tähendab, et kui nõue pole täidetud, ei käivitata skripti üldse ning seetõttu ei saa ka skripti sees midagi selle suhtes ette võtta.

Kui Sa jooksutad oma skripte erinevate Powershelli versioonide peal, siis on vaja ka seda kontrollida.  Selleks oli kaks meetodit:

if ($PSVersionTable.PSVersion -lt "5.0") {
  throw "see on vale PowerShelli versioon"
}

#Requires -Version 5.0

Neist esimese puhul ei pea tingimata skripti tööd katkestama.

Windows 8-st alates hakkasid Powershelli moodulid kaasa tulema ka opsüsteemiga.  Samuti on vaja moodulite olemasolu kontrollida juhul, kui kasutada mõnd lisatud funktsionaalsust.  Ka seda saab kahte moodi teha:

if (-not (get-module Hyper-V -ListAvailable)) {
  Write-Error "Vajalik funktsioon puudu, katkestan" -EA Stop
}

#Requires -Modules Hyper-V

Vajadusel saab kontrollida ka mooduli versiooni:

$ModuleId = @{ModuleName='Hyper-V';ModuleVersion="2.0.0.0"}
if (-not (Get-Module -FullyQualifiedName $ModuleId -ListAvailable)) {
  throw "Vajalik moodul puudu, katkestan"
}

#Requires -Modules @{ModuleName="Hyper-V";ModuleVersion="2.0.0.0"}

Kui moodulite halduseks on oma koodihoidla, siis saab muidugi lihtsamalt:

#Requires -RunAsAdministrator
#Requires -Modules PowerShellGet
Find-Module UserProfile -MinimumVersion 1.0 -Repository PSGallery |
  Install-Module -Force -Scope AllUsers

Get-InstalledModule | Update-Module

Aga vahel ei piisa ka mooduli olemasolu/versiooni kontrollist.  Näiteks on Windows 8.1-ga kaasas olevas moodulis (NetTCPIP) olemas käsk Test-NetConnection, mida Windows 8-ga kaasas olevas moodulis pole.  Aga mooduli versiooninumber on mõlemal sama.  Siis tuleb kontrollida konkreetse käsu olemasolu:

if (Get-Command Test-NetConnection -ErrorAction SilentlyContinue) {
  #olemas, võib tegutseda
} else {
  Write-Error "käsk puudu"
}

Get-Command telnet

Vahel oleks vaja hoopis teada, kas mõni opsüsteemi funktsioon on antud masinas olemas või puudu.  Windows Serveri haldusliidesed on funktsionaalsustest eraldi paigaldatavad ning võivad paikneda hoopis teises masinas.  Serveriga on asi lihtne.  Kui skripti jooksutavas masinas on ServerManager moodul (seda saab ka klient-OSile paigaldada, kui tõmmata omale RSAT), töötab järgmine kood:

if (-not (Get-WindowsFeature -Name RSAT-DNS-Server).Installed) {
  Install-WindowsFeature -Name RSAT-DNS-Server
}
#olemas, võib tegutseda

Klient-OSi puhul on see natuke keerulisem, kuna alates Win10 v1607-st otsustati osad OS funktsioonid muuta teistsuguseks, kui ülejäänud. Ja loomulikult tuli siis nende haldamiseks ka uued käsud välja mõelda:

#Requires -Modules Dism
#Requires -RunAsAdministrator

$Feature = Get-WindowsOptionalFeature -Online -FeatureName telnet*
if ($Feature.State -eq [Microsoft.Dism.Commands.FeatureState]::Disabled) {
  Enable-WindowsOptionalFeature -Online -FeatureName TelnetClient
}

# Win10/Srv16/Srv19
if (Get-Command Get-WindowsCapability -ErrorAction SilentlyContinue) {
  Get-WindowsCapability -Online -Name OpenSSH.Client*
}

Käsk Get-WindowsCapability on jälle üks neist, mis lisati tema moodulisse ilma mooduli versiooninumbrit muutmata. Ja ka Windows Sever (2016 või värskem) omab sama häda.

Edasi jääb veel vaid üle kontrollida, et kas meil on käes server-OS või midagi muud:

#Requires -Modules CimCmdlets
switch ((Get-CimInstance Win32_OperatingSystem).ProductType) {
  1 { "Workstation"}
  2 { "DC" }
  3 { "Server" }
}

Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" |
  Select-Object -Property EditionId, InstallationType

#Requires -Modules Dism
#Requires -RunAsAdministrator
if ((Get-WindowsEdition -Online).Edition -like 'Server*') {
  "on server"
} else {
  "klient, vist"
}

Server OS-i puhul võib veel tekkida vajadus teha vahet Semi-Annual Channel ja Long-Term Support Channel masinate vahel. Dokumentatsioonis on ära toodud kood, millega vajalik info kätte saada, ent neid on veel:

# ettevalmistus
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"

$Product = (Get-ItemProperty -Path $RegPath).ProductName
$Edition = (Get-ItemProperty -Path $RegPath).EditionId

#Requires -Modules CimCmdlets
$Product = (Get-CimInstance Win32_OperatingSystem).Caption

#Requires -Modules Dism
#Requires -RunAsAdministrator
$Edition = (Get-WindowsEdition -Online).Edition

# lõplik kontroll
switch -wildcard ($Edition) {
  'Server*ACor' {
    "Semi-Annual Channel"
    break
  }
  'Server*' {
    "Long-Term Support Channel or older than Server 2016"
  }
  Default { 'Not a Server product' }
}

switch -regex ($Product) {
  'Server 201[69] ' {
    "Long-Term Support Channel"
    break
  }
  ' Server [DS]' {
    "Semi-Annual Channel"
 }
}

Olen seni teadlikult vältinud OS versiooni kontrolli.  nagu ülaltpoolt näha, pole seda enamasti vaja.  Ent arvestades Windows 10 (ja Windows Serveri) väljalaske tsükliga, võib seda vaja minna:

if ([environment]::OSVersion.Version -ge "6.3") {
  "Windows 8.1 või värskem"
}

Õnnetuseks otsustas Microsoft antud viisile panna peale kontrolli: kui rakendus ise ei deklareeri, et ta tunneb uuemaid OS versioone, siis valetatakse talle versiooniks alati “6.2.9200” ehk siis Windows 8/Server 2012. Tundub, et Powershell 4 ja värskem deklareerib, ent algusepoole oli ka seal näha valet versiooni, seetõttu ei saa tagastatud vastuses alati kindel olla.  Lisaks on Windows 10 versiooninumbri algus kõigil väljalasetel sama, muutub ainult BuildNumber.  Seda viimast aga saab kontrollida:

#Requires -Modules CimCmdlets
switch ((Get-CimInstance Win32_OperatingSystem).BuildNumber) {
  {[int]$_ -lt 10240} {"Pre-Win10 version"}
  10240 {"Win10 RTM"}
  10586 {"Win10 1511"}
  14393 {"Win10/Svr16 1607"}
  15063 {"Win10 1703"}
  16299 {"Win10/Svr 1709"}
  17134 {"Win10/Svr 1803"}
  17763 {"Win10/Svr19/Svr 1809"}
  18362 {"Win10/Svr 1903"}
  18363 {"Win10/Svr 1909"}
  19041 {"Win10/Svr 2004"}
  default {"Insider/future build"}
}

Tegelikult saaks siin registrist info mugavamini kätte:

#Requires -Version 5.0
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
Get-ItemPropertyValue -Path $RegPath -Name ReleaseId

Get-CimInstance kasutamine võimaldab teha kontrolli ka eemalt.  Samamoodi saab ka versiooninumbri kätte.  Tuleb lihtsalt arvestada, et CIM tagastab versiooninumbri kui stringi ja see tuleb ise versiooninumbriks teisendada, kui seda vaja peaks olema:

#Requires -Modules CimCmdlets
(Get-CimInstance Win32_OperatingSystem).Version -as [version]

Varem oli vahel vaja ka teada Service Pack versiooni, aga uuemater versioonide puhul pole neid enam välja antud. Igaks juhuks paneme siia kirja selle tuvastamise moodused:

# text
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
Get-ItemProperty -Path $RegPath |
  Select-Object -Property CSDVersion

# number
$ServicePack = [environment]::OSVersion.Version.MajorRevision
if ($ServicePack -lt 2) {
  Write-Error 'Service Pack level too low'
}