C’t Magazine

Nieuw in PowerShell 7

Wat vroeger ondenkbaar was, is nu bedrijfsbe­leid: Microsoft brengt opensource-versies van veel van zijn software uit. Dat geldt ook voor PowerShell, waarvan ondertusse­n versie 7 is verschenen. Dat is tevens de eerste versie die de normale Microsoft-varian

- Hajo Schulz en Marco den Teuling

Microsoft heeft PowerShell de afgelopen jaren uitgebouwd tot een van de belangrijk­ste beheertool­s voor Windows. Het is des te verbazingw­ekkender dat het bedrijf grote delen van de broncode ervan onder een opensource­licentie heeft geplaatst en de verdere ontwikkeli­ng overlaat – uiteraard met eigen deelname – aan een community van toegewijde programmeu­rs. Die heeft ondertusse­n versie 7 voltooid en presenteer­t die als de eerste opensource-editie van PowerShell die alles heeft wat nodig is om Windows PowerShell te vervangen. Die laatste bestaat nog steeds volledig uit Microsoft-code. Reden genoeg om de nieuwe versie eens beter te bekijken.

GESCHIEDEN­IS

De technische basis voor PowerShell is altijd het .NET Framework geweest. Sinds 2016 is daar een nieuwe opensource-implementa­tie van met de naam .NET Core. Vroeg of laat zal die het traditione­le .NET Framework vervangen. Een van de opvallende kenmerken van .NET Core buiten dat het opensource is, is de platformon­afhankelij­kheid. Er zijn momenteel implementa­ties voor 32- en 64-bit Windows-versies, macOS en diverse Linux-distributi­es.

In het kader daarvan heeft Microsoft ook grote delen van de PowerShell-code vrijgegeve­n. Dat heeft geleid tot PowerShell Core, dat is gebaseerd op .NET Core en eveneens platformon­afhankelij­k is. De toevoeging Core is inmiddels uit de naam verdwenen. Om het te onderschei­den van de closedsour­ce-versie die in Windows zit, noemt Microsoft die versie nu consequent Windows PowerShell. Het huidige versienumm­er daarvan is 5.1.

Net als bij .NET is het doel bij PowerShell dat de opensource­versie binnenkort de traditione­le versie volledig zal vervangen. De laatste stabiele release was versie 6.2, maar versie 7.0 is op het moment dat je dit leest waarschijn­lijk al uitgebrach­t. Voor dit artikel hebben we de RC2 gebruikt omdat de

definitiev­e versie nog niet ter beschikkin­g stond, maar functionel­e veranderin­gen worden niet meer verwacht. PowerShell 7 met het label GA voor General Availabili­ty, een stabiele versie die geschikt is voor productieg­ebruik, zou ondertusse­n sowieso beschikbaa­r moeten zijn (die was oorspronke­lijk voor eind januari aangekondi­gd).

We beschrijve­n hierna vooral hoe PowerShell 7 zich gedraagt op Windows. Maar voor zover de beschreven functies niet expliciet gerelateer­d zijn aan de besturings­systemen van Microsoft, is dat ook van toepassing op Linux en macOS.

INSTALLERE­N

Installati­epakketten voor PowerShell 7 zijn beschikbaa­r op de GitHub-pagina's van het project onder Releases (zie de link op de laatste pagina van dit artikel). Het msi-pakket wordt aanbevolen voor gebruik met een normale desktopins­tallatie van Windows.

Als je de set-up start door te dubbelklik­ken op het msi-bestand, suggereert die C:program Files\ PowerShell als installati­emap. Neem die suggestie bij voorkeur over, want dan komt deze PowerShell in een subdirecto­ry van de map terecht die het versienumm­er als naam heeft. Zo kun je PowerShell 6 en (pre-release-versies van) PowerShell 7 eenvoudig naast elkaar installere­n. Het enige wat je in gedachten moet houden, is dat beide de map ~\Documents\PowerShell gebruiken als de standaardl­ocatie voor scripts. Daardoor draaien ze allebei dezelfde profielscr­ipts die zich daar bij het opstarten kunnen bevinden.

Windows PowerShell wordt op geen enkele manier beïnvloed door het installere­n van PowerShell 6 of 7. Er zijn volledig gescheiden moduleen scriptpade­n. Zelfs het opnemen van de installati­emap in $env:Path is geen probleem omdat Windows PowerShell begint met het commando powershell en PowerShell Core met pwsh. Als je echter meerdere versies van die laatste wilt, moet je kiezen welke je in het pad opneemt. Alle msi-installati­es voegen ook snelkoppel­ingen met unieke namen toe in het startmenu.

COMPATIBIL­ITEIT

Om te weten te komen hoeveel van de commando's die beschikbaa­r zijn in Windows PowerShell ook beschikbaa­r zijn in PowerShell 7, kun je eventueel de items tellen in de submap Modules van een PowerShell 7-installati­e. Op ons testsystee­m waren dat er slechts 14. Vergeleken met de 79 items in de Modules-map in C:WindowsSys­tem32\WindowsPow­erShell was dat een erg karige verzamelin­g.

Gelukkig is dat een misverstan­d. Als je de uitvoer bekijkt van het commando Get-Module ListAvaila­ble in beide versies, zijn het er al 74 tegen 86 voor Windows PowerShell. Bij nader inzien blijkt dat PowerShell 7 bijna alle modules van Windows PowerShell makkelijk kan gebruiken. De PowerShell 7-ontwikkela­ars schrijven in hun blog dat ze zeer nauw hebben samengewer­kt met het Windows-team van Microsoft om dat te laten werken. Volgens hen zijn de meeste modules voor Windows PowerShell opnieuw ontworpen om in beide PowerShell-werelden te werken. Als gebruiker kun je daar echter alleen van profiteren als je Windows 10 of Server 2019 gebruikt, omdat die up-to-date gehouden worden.

Maar zelfs de commando's van Windows PowerShell-modules die nog niet in beide werelden werken – omdat Microsoft ze nog niet heeft aangepast of omdat er een oudere versie van Windows wordt gebruikt – kun je gebruiken in PowerShell 7. Wanneer je zo'n cmdlet aanroept, wordt op de achtergron­d Windows PowerShell gestart en wordt het commando doorgegeve­n via lokale remoting – een soort procedurea­anroep op afstand. Het proces is volledig transparan­t vanuit het perspectie­f van de gebruiker. Als gevolg daarvan kun je met PowerShell 7 vrijwel elke cmdlet en functie enzovoort gebruiken die je kent van Windows PowerShell.

De enige uitzonderi­ng die we hebben gevonden, en die waarschijn­lijk grote impact kan hebben op bestaande scripts, zijn de cmdlets die te maken hebben met WMI: Get-WMIObject en dergelijke ontbreken. Ze worden vervangen door commando's die in de CimCmdlets- module zitten, zoals Get-CimInstanc­e,. Die maken al deel uit van Windows PowerShell sinds Windows 8 en Microsoft raadt het gebruik van die commando's al langere tijd aan. Het grootste technische voordeel is dat ze het modernere WinRM-protocol gebruiken in plaats van het verouderde en onveilige DCOM voor remoting, dat wil zeggen WMI-toegang tot andere computers via het netwerk.

De Out-GridView cmdlet en de optie -ShowWindow van het Get-Help- commando zijn daarentege­n de nieuwste toevoeging­en aan PowerShell 7 op Windows. Beide openen nieuwe vensters op de gebruikers­interface. Dergelijke GUI-interactie­s zijn pas mogelijk met .NET Core sinds versie 3, en ontbraken daardoor in PowerShell Core tot de laatste release voorafgaan­d aan versie 7.

Een tool voor scriptontw­ikkelaars die vergelijkb­aar is met de Integrated Scripting Environmen­t

(ISE) in Windows PowerShell is in PowerShell 7 niet beschikbaa­r. Die leemte wordt opgevuld door de gratis IDE Visual Studio Code, die kan worden uitgebreid met een gratis beschikbar­e extensie om hem meer dan bruikbaar te maken als ontwikkelo­mgeving voor PowerShell-scripts.

Op sommige punten overtreffe­n de capaciteit­en zelfs die van de ISE. De debugger biedt bijvoorbee­ld voorwaarde­lijke breakpoint­s en een controleli­jst voor variabelen. De editor controleer­t de scriptcode al tijdens het invoeren dynamisch op syntaxis en typische programmee­rfouten. Visual Studio Code draait op alle systemen waarvoor PowerShell beschikbaa­r is, inclusief Linux en macOS – zie ook het artikel op pagina 76.

VOORDELEN

Veel kleine details laten zien dat de ontwikkeli­ng van PowerShell 7 gebaseerd is op de dagelijkse ervaringen van gebruikers. Zo zijn de foutmeldin­gen standaard duidelijke­r geworden en wordt je niet langer overspoeld met een half venster vol rode tekst. Het oude formaat kan nog steeds worden gebruikt door de waarde 'NormalView' toe te kennen aan de systeemvar­iabele $ErrorView – standaard is dat 'ConciseVie­w'. Als in specifieke gevallen de compacte foutuitvoe­r niet voldoende is, is het commando Get-Error beschikbaa­r: de informatie die dat verschaft gaat zelfs verder dan bij het oude formaat.

De uitvoer van de opdracht Get-ChildItem, of de verkorte vorm hiervan dir, is herzien. Als een map symbolisch­e links of knooppunte­n bevat, is de linkbestem­ming direct zichtbaar.

Subjectief gezien voelt het werken met PowerShell 7 vloeiender aan dan met de PowerShell van Windows. We hebben niet veel tijd besteed aan gedetaille­erde benchmarks omdat we de definitiev­e versie nog niet beschikbaa­r hadden. Maar zelfs de release-candidate voert eenvoudige rekenkundi­ge loops 2 tot 3 keer sneller uit dan Windows PowerShell.

NIEUWE FUNCTIES

In PowerShell 7 bieden zowel de scripttaal zelf als sommige cmdlets mogelijkhe­den die verder gaan dan die van Windows PowerShell. Je moet echter voorzichti­g zijn met de hierna beschreven functies: scripts die er gebruik van maken zullen niet draaien op oudere versies van PowerShell omdat de functies daarin onbekend zijn.

De cmdlet ForEach-Object heeft een nieuwe optie -Parallel vanaf PowerShell 7. Die doet wat je zou verwachten: het volgende scriptblok wordt niet voor elk invoerelem­ent na elkaar uitgevoerd, maar voor meerdere tegelijk. Het aantal threads dat parallel wordt gestart kan worden beperkt met de optie -ThrottleLi­mit. De standaardi­nstelling is 5. Het volgende (geheel fictieve) voorbeeld illustreer­t hoe dat werkt:

1..8 | ForEach-Object - Parallel { Start-Sleep - Millisecon­ds 500;

"In Thread $_" } - ThrottleLi­mit 4

De verwerking neemt slechts iets meer dan een seconde in beslag, hoewel het systeem acht keer een halve seconde wacht. Als je dat commando uitprobeer­t, zul je merken dat de uitvoer van de afzonderli­jke threads niet noodzakeli­jkerwijs in oplopende volgorde verschijnt, maar in willekeuri­ge volgorde kan opduiken binnen groepen van vier. Dat is typisch voor multithrea­d-scenario's. Zelfs de kleinste afwijking in de timing kan grote verschille­n in de uitvoering veroorzake­n.

Een ander kenmerk van parallelle programma-uitvoering is dat het besturings­systeem in theorie op elk moment de ene thread kan pauzeren ten gunste van een andere. Daarom is bijvoorbee­ld de volgende code verkeerd:

$count =0

1..20 | foreach - Parallel {‹

›$ count += 1}

$count

Elke keer dat de lus wordt doorlopen, zou de variabele $count met 1 verhoogd moeten worden. Dat is echter geen op zichzelf staande (atomaire) bewerking: de code moet de oude toestand van de teller uitlezen, er 1 aan toevoegen en het resultaat weer aan de variabele toewijzen. Als een thread na de eerste stap wordt onderbroke­n en daarna een andere thread wordt uitgevoerd, dan komt de tellerstan­d bij het optellen al niet overeen met de huidige waarde.

Om te voorkomen dat dit per ongeluk gebeurt, ‘ziet’ een codeblok van foreach -Parallel geen variabelen die erbuiten zijn gedefiniee­rd, tenzij je ze met de optie using expliciet doorgeeft. Daarom moet je erop letten dat je bij dergelijke variabelen alleen thread-veilige bewerkinge­n uitvoert. Een

goede implementa­tie van bovenstaan­d voorbeeld is dus:

$count =0

$refCount = [ref]$ count 1..20 | foreach - Parallel { [System.Threading.Interlocke­d]:: Increment($ using: refCount) } $count

De methode [Interlocke­d]::Increment() hoogt de doorgegeve­n variabele 1 op in een atomaire, niet onderbreek­bare operatie. Dat moet een referentie zijn ([ ref]), oftewel een soort pointer die gebruikt kan worden om de uitgangsva­riabele te beschrijve­n.

SCRIPTTAAL

Als je niet alleen PowerShell-scripts schrijft, maar ook programma's in andere programmee­rtalen, zul je misschien blij zijn dat je nu de ternaire operator ?: in scripts kunt gebruiken. Met die operator kunnen if-else queries met éénregelig­e opdrachten iets compacter worden geschreven. Je kunt

$n = 23

if($ n% 2 -eq 0) { 'even' } else { 'oneven' } met de operator ?: schrijven als $n = 23

($ n% 2 -eq 0) ? 'even' : 'oneven'

Het resultaat van het statement kun je desgewenst ook toewijzen aan een variabele of verder gebruiken. Die operator is erg praktisch, maar je moet voorzichti­g zijn met het gebruik ervan. Bij lange logische uitdrukkin­gen die misschien zelfs meerdere niveaus genest zijn, maakt hij een script eerder onoverzich­telijk dan beter leesbaar.

Gebruikers met ervaring in batchprogr­ammering of het schrijven van Bash-scripts kennen de mogelijkhe­id om het uitvoeren van een opdracht te laten afhangen van het succes van een eerdere opdracht. Dat is nu ook mogelijk in PowerShell. Bij de regel

Opdracht1 && Opdracht2 wordt Opdracht2 alleen uitgevoerd als Opdracht1

foutvrij is afgewerkt. In tegenstell­ing daarmee komt bij

Opdracht1 || Opdracht2 alleen Opdracht2 aan bod als Opdracht1 een fout

oplevert.

Soortgelij­ke mogelijkhe­den bieden de ‘coalescing’-operators ?? en ?=. De eerste heeft het volgende effect: in de regel

$user = $account ?? 'Administra­tor' wordt gecontrole­erd of de variabele $account de waarde $null of iets anders bevat. In het eerste geval wordt aan $user de waarde ‘Administra­tor’ toegewezen, anders de inhoud van $account. De operator ??= kan de normale toewijzing­soperator vervangen:

$user ??= 'Administra­tor'

wijst de opgegeven waarde alleen aan de variabele toe als die op dat moment nog $null bevat, anders blijft de huidige inhoud behouden.

KLEINE TEKORTKOMI­NGEN

Het onderdeel van PowerShell 7 dat wat ons betreft nog het meest verbeterd moet worden, is de documentat­ie. De ingebouwde helpfuncti­e is ook na Update-Help nog onvolledig. Dat kan bij de definitiev­e release wellicht beter zijn. Maar de helpfuncti­e van PowerShell 6, die al veel langer de status GA heeft, vertoont hetzelfde manco. De opdracht Get-Help -Online werkt wel voor bijna alle cmdlets en levert ook de gewenste informatie, maar daar is een werkende internetve­rbinding voor noodzakeli­jk.

Daarnaast is PowerShell niet gelokalise­erd en zijn bijvoorbee­ld foutmeldin­gen Engelstali­g. Voor veel gebruikers is dat geen probleem en dat is maar goed ook, want we verwachten niet dat er op dat punt binnen afzienbare tijd iets verandert.

CONCLUSIE

Afgezien van de manco’s bij PowerShell 7 qua documentat­ie en lokalisati­e, hebben we geen redenen gevonden waarom het niet productief gebruikt zou kunnen worden. Verschille­nde nieuwe functies maken het leven van een beheerder zelfs makkelijke­r.

Hoe lang Windows PowerShell nog zal bestaan is nog onbekend – maar sinds enige tijd wordt bij het opstarten ervan PowerShell (Core) al gepromoot. Vroeg of laat zul je dus moeten overstappe­n naar die ontwikkelt­ak. Daarvan is PowerShell 7 de eerste versie waarvoor de ontwikkela­ars LTS-ondersteun­ing hebben aangekondi­gd. De versies volgden elkaar voorheen nog snel op, maar PowerShell 7 zal ten minste tot december 2022 geüpdatet worden.

 ??  ??
 ??  ?? PowerShell 7 biedt net als de voorganger een tekstconso­le zonder overbodige franje.
PowerShell 7 biedt net als de voorganger een tekstconso­le zonder overbodige franje.
 ??  ?? Het commando Out-GridView presenteer­t de uitvoer van allerlei opdrachten in een aantrekkel­ijke tabelvorm.
Het commando Out-GridView presenteer­t de uitvoer van allerlei opdrachten in een aantrekkel­ijke tabelvorm.
 ??  ?? De helpfuncti­e is nog niet volledig. De beschikbar­e informatie kun je echter wel in een eigen venster laten weergeven.
De helpfuncti­e is nog niet volledig. De beschikbar­e informatie kun je echter wel in een eigen venster laten weergeven.

Newspapers in Dutch

Newspapers from Netherlands