Comment utiliser un fichier de commandes pour faciliter l’exécution des scripts PowerShell
Pour plusieurs raisons, principalement liées à la sécurité, les scripts PowerShell ne sont pas aussi faciles à transporter et à utiliser que les scripts de traitement par lots. Toutefois, nous pouvons regrouper un script de traitement par lots avec nos scripts PowerShell pour résoudre ces problèmes. Ici, nous allons vous montrer quelques-uns de ces problèmes et comment construire un script batch pour les résoudre..
Pourquoi ne puis-je pas simplement copier mon fichier .PS1 sur un autre ordinateur et l'exécuter?
Sauf si le système cible a été préconfiguré pour autoriser l'exécution de scripts arbitraires, avec les privilèges requis et avec les paramètres appropriés, il y a des chances que vous rencontriez des problèmes en essayant de le faire..
- PowerShell n'est pas associé à l'extension de fichier .PS1 par défaut.
Nous en avons parlé initialement dans notre série PowerShell Geek School. Windows associe les fichiers .PS1 au Bloc-notes par défaut au lieu de les envoyer à l'interpréteur de commandes PowerShell. Cela permet d'éviter l'exécution accidentelle de scripts malveillants en double-cliquant simplement dessus. Vous pouvez modifier ce comportement de différentes manières, mais ce n’est probablement pas quelque chose que vous souhaitez faire sur tous les ordinateurs sur lesquels vous transportez vos scripts - en particulier si certains de ces ordinateurs ne sont pas les vôtres.. - PowerShell n'autorise pas l'exécution de script externe par défaut.
Le paramètre ExecutionPolicy de PowerShell empêche l’exécution de scripts externes par défaut dans toutes les versions de Windows. Dans certaines versions de Windows, la valeur par défaut n'autorise pas l'exécution de script. Nous vous avons montré comment modifier ce paramètre dans Comment autoriser l'exécution de scripts PowerShell sous Windows 7. Toutefois, il s'agit également d'une opération que vous ne souhaitez pas effectuer sur n'importe quel ordinateur.. - Certains scripts PowerShell ne fonctionneront pas sans autorisations d'administrateur.
Même avec un compte de niveau administrateur, vous devez toujours utiliser le contrôle de compte d'utilisateur pour effectuer certaines actions. Nous ne voulons pas désactiver ceci, mais c'est quand même bien quand on peut le rendre un peu plus facile à gérer. - Certains utilisateurs peuvent avoir des environnements PowerShell personnalisés..
Vous ne rencontrerez probablement pas ce problème souvent, mais lorsque vous le ferez, l'utilisation et le dépannage de vos scripts peuvent s'avérer un peu frustrants. Heureusement, nous pouvons contourner ce problème sans apporter de modifications permanentes..
Étape 1: double-cliquez pour exécuter.
Commençons par aborder le premier problème - les associations de fichiers .PS1. Vous ne pouvez pas double-cliquer pour exécuter les fichiers .PS1, mais vous pouvez exécuter un fichier .bat de cette façon. Nous allons donc écrire un fichier de commandes pour appeler le script PowerShell à partir de la ligne de commande..
Il n'est donc pas nécessaire de réécrire le fichier de commandes pour chaque script. Chaque fois que nous déplaçons un script, une variable auto-référencée est utilisée pour créer le chemin du fichier du script PowerShell. Pour que cela fonctionne, le fichier de commandes doit être placé dans le même dossier que votre script PowerShell et porter le même nom de fichier. Par conséquent, si votre script PowerShell s'appelle «MyScript.ps1», vous devrez nommer votre fichier de traitement par lots «MyScript.bat» et vous assurer qu'il se trouve dans le même dossier. Ensuite, mettez ces lignes dans le script batch:
@ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE
S'il n'y avait pas d'autres restrictions de sécurité en place, il suffirait d'exécuter un script PowerShell à partir d'un fichier de commandes. En fait, la première et la dernière ligne sont principalement une question de préférence - c'est la deuxième ligne qui fait vraiment le travail. Voici la ventilation:
@ÉCHO OFF désactive la commande faisant écho. Cela empêche simplement vos autres commandes de s'afficher à l'écran lors de l'exécution du fichier de commandes. Cette ligne est elle-même cachée par l'utilisation du symbole at (@) devant elle.
PowerShell.exe - Commande “& '% ~ dpn0.ps1'” exécute en réalité le script PowerShell. PowerShell.exe peut bien sûr être appelé depuis n’importe quelle fenêtre CMD ou fichier batch pour lancer PowerShell sur une console nue, comme d’habitude. Vous pouvez également l'utiliser pour exécuter des commandes directement à partir d'un fichier de commandes, en incluant le paramètre -Command et les arguments appropriés. La manière dont cela est utilisé pour cibler notre fichier .PS1 correspond à la variable spéciale% ~ dpn0. Exécuté à partir d'un fichier de commandes,% ~ dpn0 correspond à la lettre du lecteur, au chemin du dossier et au nom du fichier (sans extension) du fichier de commandes. Le fichier de commandes et le script PowerShell se trouvant dans le même dossier et portant le même nom,% ~ dpn0.ps1 sera traduit dans le chemin d'accès complet du script PowerShell..
PAUSE met juste en pause l'exécution du lot et attend la saisie de l'utilisateur. Cela est généralement utile d'avoir à la fin de vos fichiers de commandes, de sorte que vous ayez une chance de revoir toute sortie de commande avant que la fenêtre ne disparaisse. En testant chaque étape, son utilité deviendra plus évidente..
Ainsi, le fichier batch de base est configuré. À des fins de démonstration, ce fichier est enregistré sous le nom «D: \ Script Lab \ MyScript.bat» et un «MyScript.ps1» se trouve dans le même dossier. Voyons ce qui se passe quand on double-clique sur MyScript.bat.
Évidemment, le script PowerShell n'a pas fonctionné, mais il faut s'y attendre, nous n'avons résolu que le premier de nos quatre problèmes. Cependant, il y a quelques éléments importants démontrés ici:
- Le titre de la fenêtre indique que le script de traitement par lots a lancé avec succès PowerShell..
- La première ligne de sortie indique qu'un profil PowerShell personnalisé est en cours d'utilisation. C'est le problème potentiel n ° 4, énuméré ci-dessus.
- Le message d'erreur illustre les restrictions ExecutionPolicy en vigueur. C'est notre problème n ° 2.
- La partie soulignée du message d'erreur (qui est générée de manière native par la sortie d'erreur de PowerShell) indique que le script de traitement par lots ciblait correctement le script PowerShell souhaité (D: \ Script Lab \ MyScript.ps1). Donc, nous savons au moins que beaucoup fonctionne correctement.
Dans ce cas, le profil est un script simple d'une ligne utilisé pour cette démonstration afin de générer une sortie chaque fois que le profil est actif. Vous pouvez également personnaliser votre propre profil PowerShell si vous souhaitez tester ces scripts vous-même. Ajoutez simplement la ligne suivante à votre script de profil:
Write-Output 'Profil personnalisé PowerShell en vigueur!'
ExecutionPolicy sur le système de test ici est défini sur RemoteSigned. Cela permet l'exécution de scripts créés localement (comme le script de profil), tout en bloquant les scripts provenant de sources externes à moins qu'ils ne soient signés par une autorité de confiance. À des fins de démonstration, la commande suivante a été utilisée pour marquer MyScript.ps1 comme provenant d'une source externe:
Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '
Cela définit le flux de données alternatif Zone.Identifier sur MyScript.ps1 afin que Windows pense que le fichier provient d'Internet. Il peut être facilement inversé avec la commande suivante:
Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone.Identifier'
Étape 2: contourner ExecutionPolicy.
Contourner le paramètre ExecutionPolicy, à partir de CMD ou d'un script batch, est en réalité assez simple. Nous modifions simplement la deuxième ligne du script pour ajouter un paramètre supplémentaire à la commande PowerShell.exe.
PowerShell.exe -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"
Le paramètre -ExecutionPolicy peut être utilisé pour modifier l'ExecutionPolicy utilisé lorsque vous créez une nouvelle session PowerShell. Cela ne persistera pas au-delà de cette session. Nous pouvons donc utiliser PowerShell de cette manière à tout moment, sans affaiblir la sécurité générale du système. Maintenant que nous avons corrigé cela, faisons un autre essai:
Maintenant que le script est correctement exécuté, nous pouvons voir ce qu'il fait réellement. Cela nous permet de savoir que nous exécutons le script en tant qu'utilisateur limité. Le script est en fait exécuté par un compte avec des autorisations d'administrateur, mais le contrôle de compte d'utilisateur est un obstacle. Bien que les détails sur la manière dont le script vérifie l'accès administrateur dépassent le cadre de cet article, voici le code utilisé pour la démonstration:
if (([[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()). IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrateur")) Write-Output 'Exécution en tant qu'administrateur!' Write-Output 'Running Limited!' Pause
Vous remarquerez également qu'il y a maintenant deux opérations «Pause» dans la sortie du script: une à partir du script PowerShell et une à partir du fichier de commandes. La raison en sera plus évidente dans la prochaine étape.
Étape 3: Obtenir un accès administrateur.
Si votre script n'exécute aucune commande nécessitant une élévation et que vous êtes pratiquement sûr de ne pas avoir à vous soucier des profils personnalisés de quelqu'un qui vous gênerait, vous pouvez ignorer le reste. Si vous exécutez des cmdlets de niveau administrateur, vous aurez besoin de cette pièce..
Malheureusement, il n’ya aucun moyen de déclencher l’élévation du contrôle de compte d'utilisateur dans un fichier de commandes ou une session CMD. Cependant, PowerShell nous permet de le faire avec Start-Process. Lorsqu'il est utilisé avec «-Verb RunAs» dans ses arguments, Start-Process essaiera de lancer une application avec des autorisations d'administrateur. Si la session PowerShell n'est pas déjà élevée, cela provoquera une invite UAC. Pour utiliser cela à partir du fichier de commandes pour lancer notre script, nous allons créer deux processus PowerShell - un pour lancer Start-Process et un autre, lancé par Start-Process, pour exécuter le script. La deuxième ligne du fichier de commandes doit être modifiée en ceci:
PowerShell.exe -Command "& Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Lorsque le fichier de commandes est exécuté, la première ligne de sortie que nous verrons provient du script de profil PowerShell. Ensuite, il y aura une invite UAC lorsque Start-Process essaiera de lancer MyScript.ps1.
Après avoir cliqué sur l'invite UAC, une nouvelle instance de PowerShell va apparaître. Comme il s'agit d'une nouvelle instance, nous verrons bien sûr à nouveau la notification de script de profil. Ensuite, MyScript.ps1 s'exécute et nous constatons que nous sommes bien dans une session surélevée..
Et il y a la raison pour laquelle nous avons deux pauses ici aussi. Sans celui du script PowerShell, nous ne verrions jamais la sortie du script - la fenêtre PowerShell apparaîtrait et disparaîtrait dès que le script serait en cours d'exécution. Et sans la pause dans le fichier de commandes, nous ne pourrions pas voir s'il y avait des erreurs lors du lancement de PowerShell..
Étape 4: contournement des profils PowerShell personnalisés.
Débarrassons-nous de cette vilaine notification de profil personnalisé maintenant, d'accord? Ici, cela n’est guère gênant, mais si le profil PowerShell d’un utilisateur modifie les paramètres, les variables ou les fonctions par défaut d’une manière que vous n’auriez peut-être pas anticipée avec votre script, cela peut être très gênant. Il est beaucoup plus simple d'exécuter votre script sans le profil afin d'éviter de vous inquiéter. Pour cela, il suffit de modifier une seconde fois la deuxième ligne du fichier batch:
PowerShell.exe -NoProfile -Command "& Processus de démarrage PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
L'ajout du paramètre -NoProfile aux deux instances de PowerShell lancées par le script signifie que le script de profil de l'utilisateur sera complètement ignoré lors des deux étapes et que notre script PowerShell s'exécutera dans un environnement par défaut assez prévisible. Ici, vous pouvez voir qu’il n’ya pas d’avis de profil personnalisé dans l’un des coquillages créés.
Si vous n'avez pas besoin des droits d'administrateur dans votre script PowerShell et que vous avez sauté l'étape 3, vous pouvez vous passer de la deuxième instance de PowerShell et la deuxième ligne de votre fichier de commandes doit ressembler à ceci:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"
La sortie ressemblera alors à ceci:
(Bien sûr, pour les scripts non-administrateur, vous pouvez également vous passer d'une pause de fin de script dans votre script PowerShell, car tout est capturé dans la même fenêtre de la console et y serait conservé pendant la pause à la fin de la session. le fichier batch quand même.)
Fichiers de commandes complétés.
Selon que vous ayez ou non besoin d'autorisations d'administrateur pour votre script PowerShell (et vous ne devriez vraiment pas les demander si vous n'en avez pas besoin), le fichier de commandes final doit ressembler à l'un des deux ci-dessous..
Sans accès administrateur:
@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE
Avec un accès administrateur:
@ECHO OFF PowerShell.exe -NoProfile -Command "& Processus de démarrage PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs" PAUSE
N'oubliez pas de placer le fichier de commandes dans le même dossier que le script PowerShell pour lequel vous souhaitez l'utiliser et de lui attribuer le même nom. Ensuite, quel que soit le système sur lequel vous stockez ces fichiers, vous pourrez exécuter votre script PowerShell sans avoir à vous soucier des paramètres de sécurité du système. Vous pouvez certainement faire ces modifications manuellement à chaque fois, mais cela vous évite des problèmes et vous n'aurez pas à vous soucier de revenir plus tard aux modifications..
Références:
- Exécution de scripts PowerShell à partir d'un fichier de commandes - Blog de programmation de Daniel Schroeder
- Vérification des autorisations d'administrateur dans PowerShell - Salut, scripteur! Blog