Certains codes C # exécutent un script PowerShell avec des arguments. Je veux obtenir un code de retour et une chaîne de retour de Powershell pour savoir si tout va bien dans le script Powershell.
Quelle est la bonne façon de faire cela - à la fois dans Powershell et C #
# Powershell script
# --- Do stuff here ---
# Return an int and a string - how?
# In c# I would do something like this, if this was a method:
# class ReturnInfo
# {
# public int ReturnCode;
# public string ReturnText;
# }
# return new ReturnInfo(){ReturnCode =1, ReturnText = "whatever"};
void RunPowershellScript(string scriptFile, List<string> parameters)
{
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
using (Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
{
runspace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
Pipeline pipeline = runspace.CreatePipeline();
Command scriptCommand = new Command(scriptFile);
Collection<CommandParameter> commandParameters = new Collection<CommandParameter>();
foreach (string scriptParameter in parameters)
{
CommandParameter commandParm = new CommandParameter(null, scriptParameter);
commandParameters.Add(commandParm);
scriptCommand.Parameters.Add(commandParm);
}
pipeline.Commands.Add(scriptCommand);
Collection<PSObject> psObjects;
psObjects = pipeline.Invoke();
//What to do here?
//ReturnInfo returnInfo = pipeline.DoMagic();
}
}
class ReturnInfo
{
public int ReturnCode;
public string ReturnText;
}
J'ai réussi à faire cela en utilisant des méthodes d'écriture-sortie utilisant des conventions telles que "les deux derniers psObjects sont les valeurs que je recherche", mais cela casserait facilement.
Dans votre script PowerShell, vous pouvez créer une table de hachage en fonction de vos besoins:
[hashtable]$Return = @{}
$Return.ReturnCode = [int]1
$Return.ReturnString = [string]"All Done!"
Return $Return
En code C #, gérez le psobject de cette manière
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
{
Hashtable ht = p.ImmediateBaseObject as Hashtable;
ri.ReturnCode = (int)ht["ReturnCode"];
ri.ReturnText = (string)ht["ReturnString"];
}
//Do what you want with ri object.
Si vous souhaitez utiliser un PsCustomobject comme dans le commentaire Keith Hill dans powershell v2.0:
script PowerShell:
$return = new-object psobject -property @{ReturnCode=1;ReturnString="all done"}
$return
c # code:
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
{
ri.ReturnCode = (int)p.Properties["ReturnCode"].Value;
ri.ReturnText = (string)p.Properties["ReturnString"].Value;
}
La réponse de CB. a bien fonctionné pour moi avec un changement mineur. Je ne l'ai pas vu nulle part (en ce qui concerne C # et PowerShell), donc je voulais le poster.
Dans mon script PowerShell, j'ai créé un tableau de hachage, y a stocké deux valeurs (un booléen et un int), puis l'a converti en un PSObject:
$Obj = @{}
if($RoundedResults -ilt $Threshold)
{
$Obj.bool = $true
$Obj.value = $RoundedResults
}
else
{
$Obj.bool = $false
$Obj.value = $RoundedResults
}
$ResultObj = (New-Object PSObject -Property $Obj)
return $ResultObj
Et puis dans mon code C #, j'ai fait la même chose que CB. ai fait mais je devais utiliser Convert.ToString
afin de récupérer les valeurs:
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
{
ri.ReturnCode = Convert.ToBoolean(p.Properties["ReturnCode"].Value;)
ri.ReturnText = Convert.ToString(p.Properties["ReturnString"].Value;)
}
J'ai trouvé la réponse à cela via le message StackOverflow suivant: https://stackoverflow.com/a/5577500
Où Kieren Johnstone dit:
Utilisez Convert.ToDouble (valeur) plutôt que (double) valeur. Il faut un objet et prend en charge tous les types que vous avez demandé! :)
Wow, bonne question! Je vais me prendre une balle dans la tête ...
Vous pouvez concevoir une classe en C # qui représente la structure que vous souhaitez utiliser pour transmettre des données entre les deux. Dans le script PS, vous pouvez utiliser XmlWriter pour créer une réponse XML et utiliser Write-output
pour cracher la chaîne XML.
Du côté C #, capturez la réponse standard, désérialisez le code XML dans votre nouvelle classe de réponses, puis traitez le résultat. Notez que vous ne pouvez rien écrire sur stdout autre que votre réponse XML, sinon vous ne pourrez pas désérialiser dans la classe.