Wanneer je een PowerShell-script of -functie schrijft, wil je vaak gebruikersinvoer accepteren via parameters. Als je de waarden die deze parameters accepteren niet beperkt, kun je niet garanderen dat er situaties zullen zijn waarin ongepaste waarden worden opgegeven. In dit artikel leer je hoe je de parametervalidatieattribuut ValidateSet van PowerShell kunt gebruiken om deze waarden te beperken tot alleen diegene die je definieert.
Bij het schrijven van een PowerShell-script of -functie kun je verschillende validatieattributen gebruiken om te controleren of de waarden die aan je parameters worden doorgegeven acceptabel zijn, en de gebruiker waarschuwen als dat niet het geval is.
Dit artikel richt zich op het validatieattribuut ValidateSet. Je leert wat ValidateSet doet, waarom je ValidateSet in je code zou willen gebruiken en hoe je dat kunt doen. Je leert ook over de tabcompletion-functie die wordt ingeschakeld door ValidateSet en die gebruikers van je code helpt om geldige parameterwaarden op te geven.
PowerShell ValidateSet: Een beknopt overzicht
ValidateSet is een parameterattribuut waarmee je een reeks elementen kunt definiëren die alleen worden geaccepteerd als waarde voor die parameter.
Stel bijvoorbeeld dat je een script hebt dat is gedefinieerd om te werken met Active Directory-domeincontrollers. Dit script heeft een parameter die de naam van een domeincontroller specificeert. Zou het niet logisch zijn om de lijst met acceptabele waarden te beperken tot de daadwerkelijke namen van de domeincontrollers? Er is geen reden waarom de gebruiker “foobar” als waarde zou moeten kunnen gebruiken, terwijl je van tevoren weet welke waarden het script nodig heeft. ValidateSet biedt je die mogelijkheid.
Vereisten
Dit artikel zal een leerproces zijn. Als je van plan bent om mee te doen, heb je het volgende nodig:
- Visual Studio Code of een andere code-editor. Ik zal Visual Studio Code gebruiken.
- Minstens PowerShell 5.1 voor het grootste deel van de code in dit artikel. Er is één sectie die vereist PowerShell 6.1 of later en ik zal dat identificeren wanneer we eraan toe zijn
Alle code in dit artikel is getest in de volgende omgevingen:
Operating System | PowerShell Versions |
---|---|
Windows 7 SP1 | 5.1, Core 6.2 |
Windows 10 1903 | 5.1, Core 6.2 |
Linux Mint 19.2 | Core 6.2 |
Om de concepten rond ValidateSet uit te leggen, ga je een klein script bouwen genaamd Get-PlanetSize.ps1. Dit script geeft informatie terug over de groottes van planeten in ons zonnestelsel.
Je begint met een eenvoudig script en verbetert geleidelijk zijn vermogen om input van de eindgebruiker te verwerken en het voor hen gemakkelijk te maken om de mogelijke parameterwaarden te ontdekken.
Aan de slag
Om te beginnen, kopieer en plak eerst de PowerShell-code hieronder in je favoriete teksteditor en sla het op als Get-PlanetSize.ps1.
Voer het script uit vanaf een PowerShell-prompt en je zou het volgende moeten krijgen:
Informatief maar niet erg flexibel; de informatie voor elke planeet wordt geretourneerd, zelfs als je alleen de informatie voor Mars wilt.
Misschien wil je de mogelijkheid hebben om een enkele planeet te specificeren in plaats van ze allemaal terug te krijgen. Dat zou je doen door een parameter te introduceren. Laten we eens kijken hoe we dat kunnen bereiken.
Input accepteren met behulp van een parameter
Om het script een parameter te laten accepteren, voeg je een Param()
-blok toe bovenaan het script. Noem de parameter Planeet
. Een geschikt Param()
-blok ziet er als volgt uit.
In het onderstaande voorbeeld zorgt de regel [Parameter(Verplicht)]
ervoor dat er altijd een planeetnaam aan het script wordt geleverd. Als deze ontbreekt, zal het script erom vragen.
De eenvoudigste manier om deze Planeet
-parameter in het script op te nemen, is door de regel $planets.keys | Foreach-Object {
te wijzigen in $Planeet | Foreach-Object {
. Nu vertrouw je niet meer op de hashtable die eerder statisch is gedefinieerd, maar lees je in plaats daarvan de waarde van de Planeet
-parameter.
Als je nu het script uitvoert en een planeet opgeeft met behulp van de Planeet
-parameter, zie je alleen informatie over die specifieke planeet.
Uitstekend. Is het script compleet? Misschien niet helemaal.
De opties zijn te open.
Wat gebeurt er als je probeert de diameter van de planeet Barsoom te vinden met behulp van Get-PlanetSize.ps1?
Hmm, dat klopt niet. Barsoom staat niet op de lijst van planeten, maar het script wordt toch uitgevoerd. Hoe kunnen we dit oplossen?
Het probleem hier is dat het script elk invoer accepteert en gebruikt, ongeacht of het een geldige waarde is of niet. Het script heeft een manier nodig om te beperken welke waarden worden geaccepteerd voor de Planet
-parameter. Voer ValidateSet in!
Ervoor zorgen dat alleen bepaalde waarden worden gebruikt
A ValidateSet list is a comma-separated list of string values, wrapped in single or double-quotes. Adding a ValidateSet attribute to a script or function parameter consists of adding a line of text to the Param()
block, as shown below. Replace the Param()
block in your copy of Get-PlanetSize.ps1 with the one below and save the file.
Probeer het script opnieuw uit te voeren met Barsoom als uw Planet
-parameter. Nu wordt er een nuttige foutmelding geretourneerd. Het bericht is specifiek in wat er mis is gegaan en geeft zelfs een lijst met mogelijke waarden voor de parameter.
PowerShell laten Valideren Set Hoofdlettergevoelig
Standaard is het ValidateSet-attribuut niet hoofdlettergevoelig. Dit betekent dat het elke tekenreeks zal toestaan, mits deze in de toegestane lijst staat met een willekeurig hoofdlettergebruik. Bijvoorbeeld, het bovenstaande voorbeeld zal zowel Mars
accepteren als mars
. Indien nodig kunt u afdwingen dat ValidateSet hoofdlettergevoelig is door de optie IgnoreCase
te gebruiken.
De IgnoreCase
-optie in ValidateSet is een validatieattribuut dat bepaalt of de waarden die aan de parameter worden geleverd exact overeenkomen met de lijst met geldige waarden. Standaard staat IgnoreCase
ingesteld op $True
(hoofdletters negeren). Als u dit instelt op $False
, zal het leveren van mars als waarde voor de Planet
-parameter voor Get-PlanetSize.ps1
een foutmelding genereren.
U kunt de IgnoreCase
-optie gebruiken door deze aan het einde van de lijst met geldige waarden een $true
-waarde toe te wijzen zoals hieronder getoond.
Nu wanneer je probeert een waarde te gebruiken voor Planet
die niet exact overeenkomt met een waarde in de lijst, zal validatie mislukken.
Het Gebruik van Tab Completering
Nog een voordeel van het gebruik van ValidateSet is dat het je tab completering geeft. Dit betekent dat je door de mogelijke waarden voor een parameter kunt bladeren met behulp van de TAB-toets. Dit verbetert aanzienlijk de bruikbaarheid van een script of functie, vooral vanuit de console.
In de onderstaande voorbeelden zijn een paar dingen om op te merken:
- De tab completering gaat terug naar de eerste waarde nadat de laatste is weergegeven.
- De waarden worden in alfabetische volgorde gepresenteerd, ook al zijn ze niet alfabetisch gesorteerd in de ValidateSet.
- Het typen van een initiële letter en op TAB drukken beperkt de waarden die worden aangeboden door tab completering tot die die met die letter beginnen.


Je kunt ook profiteren van ValidateSet tab completering in de PowerShell Integrated Scripting Environment (ISE), zoals weergegeven in het onderstaande voorbeeld. De ISE Intellisense-functie toont je de lijst met mogelijke waarden in een mooie selectiebox.
Intellisense retourneert alle waarden die de letter bevatten die je typt, in plaats van alleen die die ermee beginnen.

Nu we ValidateSet validatieattributen hebben behandeld zoals ze zijn in Windows 5.1, laten we eens kijken naar wat er is toegevoegd in PowerShell Core 6.1 en kijken of dat ons script meer validatiemogelijkheden kan geven.
Begrijpen van Veranderingen in ValidateSet in PowerShell 6.1
Met de komst van PowerShell Core 6.1 zijn er twee nieuwe mogelijkheden toegevoegd aan ValidateSet-validatieattributen:
- De
ErrorMessage
-eigenschap - Gebruik van klassen in ValidateSet via toegang tot
System.Management.Automation.IValidateSetValuesGenerator
De ErrorMessage-eigenschap
Het standaardfoutbericht dat wordt gegenereerd wanneer u een onjuiste planeetnaam opgeeft aan Get-PlanetSize.ps1 is nuttig, maar een beetje langdradig:
Gebruik de ErrorMessage
-eigenschap van het ValidateSet
-validatieattribuut om een ander foutbericht in te stellen, zoals weergegeven in het onderstaande voorbeeld. {0}
wordt automatisch vervangen door de ingediende waarde en {1}
wordt automatisch vervangen door de lijst met toegestane waarden.
Vervang het Param()
-blok in het scriptbestand en sla het op. Probeer vervolgens opnieuw Get-PlanetSize.ps1 -Planet Barsoom
. Let op dat de foutmelding hieronder veel minder langdradig en meer beschrijvend is.
Kijk vervolgens naar een nieuwe manier om de acceptabele waarden te definiëren in ValidateSet via een PowerShell klasse.
PowerShell-klassen
Aangepaste typen, in PowerShell bekend als klassen, zijn beschikbaar sinds versie 5. Met de komst van PowerShell Core 6.1 is er een nieuwe functie om het gebruik van een klasse toe te staan om de waarden voor ValidateSet te leveren.
Met behulp van een klasse kunt u omgaan met de belangrijkste beperking van een ValidateSet – het is statisch. Dat wil zeggen, het is ingebed als onderdeel van de functie of script en kan alleen worden gewijzigd door het script zelf te bewerken.
De nieuwe functie die werkt met ValidateSet
is de mogelijkheid om de System.Management.Automation.IValidateSetValuesGenerator-klasse te gebruiken. We kunnen dit als basis gebruiken voor onze eigen klassen met behulp van overerving. Om met ValidateSet
te werken, moet de klasse zijn gebaseerd op System.Management.Automation.IValidateSetValuesGenerator en het moet een methode implementeren genaamd GetValidValues()
.
De GetValues()
-methode retourneert de lijst met waarden die u wilt accepteren. Een Param()
-blok met de statische lijst van planeten vervangen door een [Planet]
-klasse zou er als volgt uitzien. Deze voorbeeld zal nog niet werken. Blijf lezen om te leren hoe dit te implementeren.
Het gebruik van een klasse voor een ValidateSet-waardelijst: Een echt voorbeeld
Om het gebruik van een klasse voor een ValidateSet-waardelijst te demonstreren, gaat u de statische lijst van planeten die eerder is gebruikt, vervangen door een lijst die is geladen vanuit een CSV-tekstbestand. U hoeft niet langer een statische lijst van waarden binnen het script zelf te onderhouden!
Creëren van een gegevensbron voor de klasse
Ten eerste moet u een CSV-bestand maken met elk van de geldige waarden. Kopieer hiervoor deze gegevensset en plak deze in een nieuw tekstbestand en sla het op als planets.csv in dezelfde map als het Get-PlanetSize.ps1-script.
Het toevoegen van de klasse aan het script
Elke klasse die door ValidateSet wordt gebruikt, moet al gedefinieerd zijn voordat ValidateSet probeert deze te gebruiken. Dit betekent dat de structuur van Get-PlanetSize.ps1 zoals deze is, niet zal werken.
De klasse [Planet]
moet gedefinieerd zijn voordat deze kan worden gebruikt, dus deze moet aan het begin van het script worden geplaatst. Een geschikte skeletklassedefinitie ziet er als volgt uit:
Binnen de methode GetValidValues()
van de klasse, gebruik de Import-CSV
cmdlet om het tekstbestand planets.csv dat eerder is aangemaakt, te importeren. Het bestand wordt geïmporteerd in een variabele met een globale reikwijdte, genaamd $planets
, om er later in het script toegang toe te hebben.
Gebruik de return
-verklaring om de lijst met planeetnamen via GetValidValues()
terug te geven. Na deze wijzigingen zou de klasse er nu als volgt uit moeten zien.
Vervolgens, verwijder de hash-tabelverklaring $planets
uit het script zoals hieronder wordt weergegeven. De globale variabele $planets
die wordt gevuld door de klasse [Planet]
, bevat de planeetgegevens in plaats daarvan.
Wikkel nu de resterende originele code in een functie en noem deze Get-PlanetDiameter
om deze te onderscheiden van de naam van het script. Plaats het Param()
-blok dat aan het begin van het script stond binnen de functie. Vervang de statische lijst met planeten door een verwijzing naar de klasse [Planet]
, zoals hieronder wordt weergegeven.
Vervang de regel $output = "De diameter van planeet {0} is {1} km" -f $_, $planets[$_]
door de volgende twee regels. Hierdoor kan het script een planeet opzoeken in de reeks objecten gemaakt door Import-CSV
, in plaats van de hashtable die je eerder hebt gemaakt en die je uit het script hebt verwijderd:
Na deze set wijzigingen moet je uiteindelijke script er als volgt uitzien:
Onthoud, vanaf dit punt werkt het script alleen in PowerShell 6.1 of later
Hoe gebruik je dit script?
Het Script Uitvoeren
Je kunt de nieuwe versie van het script niet direct gebruiken door eenvoudigweg het script uit te voeren. Alle bruikbare code zit nu in een functie. In plaats daarvan moet je het bestand dot sourcen om toegang te krijgen tot de functie binnen de PowerShell-sessie.
Zodra je het hebt gedot-sourced, heb je nu toegang tot de nieuwe functie Get-PlanetDiameter
in de PowerShell-sessie, met tab-completion.
“Wat is het voordeel van al dat werk?”, hoor ik je vragen. “Het script lijkt op dezelfde manier te werken, maar het is moeilijker om de code te gebruiken!”
Probeer dit:
- Open het bestand
planets.csv
dat je eerder hebt gemaakt. - Voeg een nieuwe rij toe met een nieuwe naam en diameter.
- Sla het CSV-bestand op.
In dezelfde sessie waarin je oorspronkelijk je script hebt geïmporteerd, probeer de diameter van de nieuwe planeet op te zoeken met Get-PlanetDiameter
. Het werkt!
Het gebruik van een klasse op deze manier biedt ons verschillende voordelen:
- De lijst met geldige waarden is nu gescheiden van de code zelf, maar eventuele wijzigingen in de waarden in het bestand worden opgepikt door het script.
- Het bestand kan worden onderhouden door iemand die nooit toegang heeft tot het script.
- A more complex script could look up information from a spreadsheet, database, Active Directory or a web API.
Zoals je kunt zien, zijn de mogelijkheden bijna eindeloos bij het gebruik van een klasse om ValidateSet-waarden te leveren.
Samenvattend
We hebben veel terrein behandeld terwijl we Get-PlanetSize.ps1
hebben gebouwd, dus laten we even opfrissen.
In dit artikel heb je geleerd:
- Wat een ValidateSet-validatieattribuut is en waarom je er een zou willen gebruiken
- Hoe je ValidateSet aan een PowerShell-functie of script toevoegt
- Hoe tab-completion werkt met ValidateSet
- Hoe je de
IgnoreCase
-eigenschap gebruikt om te bepalen of je ValidateSet hoofdlettergevoelig is - Hoe je de
ErrorMessage
-eigenschap gebruikt met je ValidateSet en PowerShell 6.1 - Hoe je een klasse gebruikt om een dynamische ValidateSet te maken met PowerShell 6.1
Waar wacht je nog op? Begin vandaag nog met het gebruik van ValidateSet!
Verdere Lezing
Source:
https://adamtheautomator.com/powershell-validateset/