Hello Stack Community :)
J'ai un objectif simple. Je voudrais démarrer un script PowerShell à partir d'un autre script Powershell, mais il y a 3 conditions:
- Je dois transmettre des informations d'identification (l'exécution se connecte à une base de données qui a un utilisateur spécifique)
- Il doit prendre certains paramètres
- Je voudrais passer la sortie dans une variable
Il y a une question similaire Lien . Mais la réponse est d'utiliser des fichiers comme moyen de communication entre 2 scripts PS. Je voudrais juste éviter les conflits d'accès. @Update: Le script principal va démarrer quelques autres scripts. donc la solution avec les fichiers peut être délicate, si l'exécution sera effectuée à partir de plusieurs utilisateurs en même temps.
Script1.ps1 est le script qui doit avoir une chaîne en sortie. (Juste pour être clair, c'est un script fictif, le vrai a 150 lignes, donc je voulais juste faire un exemple)
param(
[String]$DeviceName
)
#Some code that needs special credentials
$a = "Device is: " + $DeviceName
$a
ExecuteScripts.ps1 devrait invoquer celui-là avec ces 3 conditions mentionnées ci-dessus
J'ai essayé plusieurs solutions. Celui-ci par exemple:
$arguments = "C:\..\script1.ps1" + " -ClientName" + $DeviceName
$output = Start-Process powershell -ArgumentList $arguments -Credential $credentials
$output
Je ne reçois aucune sortie de cela et je ne peux pas simplement appeler le script avec
&C:\..\script1.ps1 -ClientName PCPC
Parce que je ne peux pas lui passer de -Credential
paramètre ..
Merci d'avance!
la source
Réponses:
Remarque:
La solution suivante fonctionne avec tout programme externe et capture invariablement la sortie sous forme de texte .
Pour appeler une autre instance PowerShell et capturer sa sortie en tant qu'objets riches (avec des limitations), consultez la solution variante dans la section inférieure ou considérez la réponse utile de Mathias R. Jessen , qui utilise le SDK PowerShell .
Voici une preuve de concept basée sur l'utilisation directe des types
System.Diagnostics.Process
etSystem.Diagnostics.ProcessStartInfo
.NET pour capturer la sortie du processus en mémoire (comme indiqué dans votre question,Start-Process
n'est pas une option, car il prend uniquement en charge la capture de la sortie dans des fichiers , comme indiqué dans cette réponse ) :Remarque:
En raison de l'exécution en tant qu'utilisateur différent, cela est pris en charge sous Windows uniquement (à partir de .NET Core 3.1), mais dans les deux éditions PowerShell.
En raison de la nécessité d'exécuter en tant qu'utilisateur différent et de capturer la sortie,
.WindowStyle
ne peut pas être utilisé pour exécuter la commande cachée (car l'utilisation de.WindowStyle
require.UseShellExecute
est$true
, ce qui est incompatible avec ces exigences); cependant, étant donné que toutes les sorties sont capturées , le réglage.CreateNoNewWindow
sur$true
aboutit effectivement à une exécution cachée.Ce qui précède donne quelque chose comme ce qui suit, montrant que le processus s'est correctement déroulé avec l'identité d'utilisateur donnée:
Puisque vous appelez une autre instance PowerShell , vous souhaiterez peut- être profiter de la capacité de la CLI PowerShell à représenter la sortie au format CLIXML, ce qui permet de désérialiser la sortie en objets riches , bien qu'avec une fidélité de type limitée , comme expliqué dans cette réponse associée .
Ce qui précède génère quelque chose comme ce qui suit, montrant que l'
[datetime]
instance (System.DateTime
) sortie par aGet-Date
été désérialisée en tant que telle:la source
Start-Process
serait mon dernier choix pour invoquer PowerShell à partir de PowerShell - en particulier parce que toutes les E / S deviennent des chaînes et non des objets (désérialisés).Deux alternatives:
1. Si l'utilisateur est un administrateur local et que PSRemoting est configuré
Si une session à distance contre la machine locale (malheureusement limitée aux administrateurs locaux) est une option, j'irais certainement avec
Invoke-Command
:$strings
contiendra les résultats.2. Si l'utilisateur n'est pas un administrateur sur le système cible
Vous pouvez écrire votre propre "local uniquement
Invoke-Command
" en faisant tourner un espace d'exécution hors processus en:PowerShellProcessInstance
, sous une connexion différenteJ'ai mis en place une telle fonction ci-dessous, voir les commentaires en ligne pour une procédure pas à pas:
Ensuite, utilisez comme ceci:
la source
rcv.ps1
exécution à partir d'un autre script:
production:
la source
Ce que vous pouvez faire, procédez comme suit pour passer un paramètre à un script ps1.
Le premier script peut être un origin.ps1 où l'on écrit:
Le script de destination dest.ps1 peut avoir le code suivant pour capturer les variables
Et le résultat sera
la source
-Credential $credentials
paramètre à cette exécution et en obtenir la sortie dans une variable. La ps1. L'exécution du script im lance une chaîne de mots simples à la fin. Regardez simplement comment je l'ai fait,Start-process
mais cette fonction ne génère pas de sortie$output
variable, c'est NULL. L'autre idée qui vient de @ mklement0 est d'enregistrer la sortie dans un fichier. Mais dans mon cas, cela entraînera une énorme quantité de fichiers en un seul endroit. Tous créés à partir d'utilisateurs différents avec des scripts différents