9Sep

Comment utiliser un fichier de traitement par lots pour rendre les scripts PowerShell plus faciles à exécuter

click fraud protection

Pour plusieurs raisons, principalement liées à la sécurité, les scripts PowerShell ne sont pas aussi facilement portables et utilisables que les scripts batch. Cependant, nous pouvons regrouper un script batch avec nos scripts PowerShell pour contourner ces problèmes. Ici, nous allons vous montrer quelques-uns de ces problèmes, et comment créer un script batch pour les contourner.

Pourquoi ne puis-je pas simplement copier mon fichier. PS1 sur un autre ordinateur et l'exécuter?

A moins que le système cible n'ait été préconfiguré pour permettre l'exécution de scripts arbitraires, avec les privilèges requis, et en utilisant les bons paramètres, il y a de fortes chances que vous rencontriez des problèmes lorsque vous essayerez de le faire.

  1. PowerShell n'est pas associé à l'extension de fichier. PS1 par défaut.
    Nous en avons d'abord parlé 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. Il y a des façons de changer ce comportement, mais ce n'est probablement pas quelque chose que vous voulez faire sur tous les ordinateurs sur lesquels vous allez porter vos scripts - surtout si certains de ces ordinateurs ne vous appartiennent pas.
    instagram viewer
  2. PowerShell n'autorise pas l'exécution de script externe par défaut.
    Le paramètre ExecutionPolicy dans 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, vous ne voulez pas non plus le faire sur n'importe quel ordinateur.
  3. Certains scripts PowerShell ne fonctionneront pas sans les autorisations d'administrateur.
    Même en cours d'exécution avec un compte de niveau administrateur, vous devez toujours passer par le contrôle de compte d'utilisateur( UAC) pour effectuer certaines actions. Nous ne voulons pas le désactiver, mais c'est quand même agréable de pouvoir le gérer un peu plus facilement.
  4. Certains utilisateurs peuvent avoir des environnements PowerShell personnalisés.
    Vous ne rencontrerez probablement pas ce problème souvent, mais lorsque vous le faites, cela peut rendre l'exécution et le dépannage de vos scripts un peu frustrants. Heureusement, nous pouvons contourner cela sans apporter de changements permanents.

Étape 1: Double-cliquez pour exécuter.

Commençons par aborder le premier problème - associations de fichiers. PS1.Vous ne pouvez pas double-cliquer pour exécuter des fichiers. PS1, mais vous pouvez exécuter un fichier. BAT de cette façon. Nous allons donc écrire un fichier batch pour appeler le script PowerShell à partir de la ligne de commande pour nous.

Nous n'avons donc pas besoin de réécrire le fichier batch pour chaque script, ou chaque fois que nous déplaçons un script, il va utiliser une variable autoréférentielle pour construire le chemin du fichier PowerShell. Pour que cela fonctionne, le fichier batch doit être placé dans le même dossier que votre script PowerShell et avoir le même nom de fichier. Donc, si votre script PowerShell s'appelle "MyScript.ps1", vous devrez nommer votre fichier batch "MyScript.bat" et vous assurer qu'il se trouve dans le même dossier. Ensuite, placez 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, ce serait vraiment toutil faut exécuter un script PowerShell à partir d'un fichier batch. En fait, la première et la dernière lignes sont principalement une question de préférence - c'est la deuxième ligne qui fait vraiment le travail. Voici la répartition:

@ECHO OFF désactive l'écho de commande. Cela empêche que vos autres commandes n'apparaissent à l'écran lors de l'exécution du fichier batch. Cette ligne est elle-même cachée par l'utilisation du symbole at( @) devant elle.

PowerShell.exe -Command "&'% ~ Dpn0.ps1' " exécute réellement le script PowerShell. PowerShell.exe peut bien sûr être appelé à partir de n'importe quelle fenêtre ou fichier batch CMD pour lancer PowerShell sur une console vide comme d'habitude. Vous pouvez également l'utiliser pour exécuter des commandes directement à partir d'un fichier batch, en incluant le paramètre -Command et les arguments appropriés. La façon dont ceci est utilisé pour cibler notre fichier. PS1 est avec la variable spéciale% ~ dpn0.Exécuté à partir d'un fichier de commandes,% ~ dpn0 évalue la lettre de lecteur, le chemin du dossier et le nom de fichier( sans extension) du fichier de traitement par lots.Étant donné que le fichier de commandes et le script PowerShell se trouvent dans le même dossier et ont le même nom,% ~ dpn0.ps1 se traduira par le chemin complet du script PowerShell.

PAUSE interrompt simplement l'exécution du batch et attend la saisie de l'utilisateur. Il est généralement utile d'avoir à la fin de vos fichiers de traitement par lot, de sorte que vous ayez la possibilité d'examiner toute sortie de commande avant que la fenêtre ne disparaisse. Au fur et à mesure que nous testons chaque étape, l'utilité de cette étape devient plus évidente.

Donc, le fichier batch de base est configuré.À des fins de démonstration, ce fichier est enregistré sous "D: \ Script Lab \ MyScript.bat" et il y a un "MyScript.ps1" dans le même dossier. Voyons ce qui se passe lorsque nous double-cliquez sur MyScript.bat.

Évidemment, le script PowerShell ne s'est pas exécuté, mais c'est à prévoir - nous avons seulement abordé le premier de nos quatre problèmes, après tout. Cependant, il y a quelques bits importants démontrés ici:

  1. Le titre de la fenêtre montre que le script batch a lancé avec succès PowerShell.
  2. La première ligne de sortie indique qu'un profil PowerShell personnalisé est utilisé.C'est le problème potentiel # 4, énuméré ci-dessus.
  3. Le message d'erreur montre les restrictions ExecutionPolicy en vigueur. C'est notre problème # 2.
  4. La partie soulignée du message d'erreur( qui est faite nativement par la sortie d'erreur de PowerShell) montre que le script de lot ciblait correctement le script PowerShell prévu( D: \ Script Lab \ MyScript.ps1).Nous savons donc au moins que beaucoup fonctionne correctement.

Le profil, dans ce cas, est un simple script d'une ligne utilisé pour cette démonstration pour générer une sortie à chaque fois que le profil est actif. Vous pouvez également personnaliser votre propre profil PowerShell pour ce faire, si vous souhaitez tester ces scripts vous-même. Ajoutez simplement la ligne suivante à votre script de profil:

Write-Output 'Profil PowerShell personnalisé en vigueur!'

L'objet ExecutionPolicy du système de test 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, sauf s'ils sont 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 annulé avec la commande suivante:

Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone. Identifier'

Étape 2: Déplacer ExecutionPolicy.

Le fait de contourner le paramètre ExecutionPolicy, à partir de CMD ou d'un script batch, est en fait 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 la méthode ExecutionPolicy utilisée lorsque vous générez une nouvelle session PowerShell. Cela ne persistera pas au-delà de cette session, de sorte que nous pouvons exécuter PowerShell comme ça chaque fois que nous en avons besoin sans affaiblir la posture de sécurité générale du système. Maintenant que nous avons corrigé cela, allons-y encore une fois:

Maintenant que le script a été 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 devient gênant. Bien que les détails de la vérification de l'accès administrateur par le script dépassent la portée de cet article, voici le code utilisé pour la démonstration:

if( ([Security. Principal. WindowsPrincipal] [Security. Principal. WindowsIdentity]: : GetCurrent() ). IsInRole( [Security. Principal. WindowsBuiltInRole] "Administrator")){ Write-Output 'Exécution en tant qu'administrateur!'} Else{ Write-Output 'Running Limited!'} Pause

Vous remarquerez également qu'il y a maintenant deux"Pause" des opérations dans la sortie du script - un du script PowerShell, et un du fichier batch. La raison en sera plus apparente à l'étape suivante.

Étape 3: Obtenir l'accès administrateur.

Si votre script n'exécute aucune commande nécessitant une élévation, et que vous êtes sûr que vous n'aurez pas à vous soucier des profils personnalisés d'un utilisateur, vous pouvez ignorer le reste. Si vous exécutez des cmdlets de niveau Administrateur, vous aurez besoin de cette pièce.

Malheureusement, il n'y a aucun moyen de déclencher l'UAC pour l'élévation depuis un fichier batch 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 essayera de lancer une application avec des permissions d'administrateur. Si la session PowerShell n'est pas déjà élevée, une invite UAC est déclenchée. Pour l'utiliser à partir du fichier batch pour lancer notre script, nous allons générer deux processus PowerShell: l'un pour lancer Start-Process et l'autre, lancé par Start-Process, pour exécuter le script. La deuxième ligne du fichier de commandes doit être remplacée par:

PowerShell.exe -Command "&{ Démarrer-Processus PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -VerbRunAs} "

Lorsque le fichier batch 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 essaye de lancer MyScript.ps1.

Après avoir cliqué sur l'invite UAC, une nouvelle instance PowerShell apparaît. Comme il s'agit d'une nouvelle instance, nous verrons à nouveau l'avis de script de profil. Ensuite, MyScript.ps1 s'exécute et nous voyons que nous sommes en effet dans une session élevée.

Et il y a la raison pour laquelle nous avons deux pauses ici aussi. Si ce n'est pas le cas dans le script PowerShell, nous ne verrons jamais la sortie du script - la fenêtre PowerShell apparaîtra et disparaîtra dès que le script sera exécuté.Et sans la pause dans le fichier batch, nous ne serions pas en mesure de voir s'il y a eu des erreurs de lancement de PowerShell en premier lieu.

Étape 4: Contournement des profils PowerShell personnalisés.

Débarrassons-nous de ce méchant avis de profil personnalisé maintenant, d'accord? Ici, ce n'est même pas une nuisance, 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'avez peut-être pas anticipée avec votre script, ils peuvent être vraiment gênants. Il est beaucoup plus simple d'exécuter votre script sans le profil, donc vous n'avez pas à vous en préoccuper. Pour ce faire, nous avons juste besoin de changer une fois de plus la deuxième ligne du fichier batch:

PowerShell.exe -NoProfile -Command "&{ Démarrer-Traiter 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é dans les deux étapes et que notre script PowerShell s'exécuteraun environnement par défaut assez prévisible. Ici, vous pouvez voir qu'il n'y a aucun avis de profil personnalisé dans l'une ou l'autre des coquilles générées.

Si vous n'avez pas besoin de droits d'administrateur dans votre script PowerShell et que vous avez ignoré l'étape 3, vous pouvez vous passer de la seconde instance PowerShell et la seconde ligne de votre fichier de commandes devrait ressembler à ceci:

PowerShell.exe -NoProfileExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"

La sortie ressemblera à ceci:

( Bien sûr, pour les scripts non-administrateur, vous pouvez vous passer d'une pause de fin de script dans votre script PowerShellà ce stade aussi, puisque tout est capturé dans la même fenêtre de la console et sera maintenu par la pause à la fin du fichier séquentiel de toute façon.)

Fichiers batch complétés.

Selon que vous ayez besoin ou non d'autorisations d'administrateur pour votre script PowerShell( et que vous ne devriez pas les demander si ce n'est pas le cas), le dernier fichier de commandes doit ressembler à l'un des deux suivants.

Sans accès administrateur:

@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE

Avec accès administrateur:

@ECHO OFF PowerShell.exe -NoProfile -Command "&{Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 ""' -Verb RunAs} "PAUSE

N'oubliez pas de placer le fichier batch dans le même dossier que le script PowerShell que vous voulezpour l'utiliser, et donnez-lui le même nom. Ensuite, quel que soit le système sur lequel vous utiliserez ces fichiers, vous serez en mesure d'exécuter votre script PowerShell sans avoir à manipuler les paramètres de sécurité du système. Vous pouvez certainement faire ces changements manuellement à chaque fois, mais cela vous évite ce problème et vous n'aurez pas à vous soucier de revenir sur les changements plus tard.

Références:

  • Exécution de scripts PowerShell à partir d'un fichier de traitement par lots - Blog de programmation de Daniel Schroeder
  • Vérification des autorisations d'administrateur dans PowerShell - Hey, Scripting Guy! Blog