一部のC#コードは、引数付きのpowershellスクリプトを実行します。 Powershellスクリプト内ですべてが正常であったかどうかを知るために、Powershellからリターンコードと文字列を取得したいと思います。
それを行う正しい方法は何ですか-Powershellと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;
}
Write-Outputを使用し、「最後の2つのpsObjectは私が探している値です」などの規則に依存することで、これをなんとかしてやっかいな方法にしていますが、簡単に壊れてしまいます。
PowerShellスクリプトで、必要に応じてHashtableを構築できます。
[hashtable]$Return = @{}
$Return.ReturnCode = [int]1
$Return.ReturnString = [string]"All Done!"
Return $Return
C#コードでは、この方法でPsobjectを処理します
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.
Powershell v2.0のKeith HillコメントのようにPsCustomobjectを使用する場合:
powerShellスクリプト:
$return = new-object psobject -property @{ReturnCode=1;ReturnString="all done"}
$return
c#コード:
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
{
ri.ReturnCode = (int)p.Properties["ReturnCode"].Value;
ri.ReturnText = (string)p.Properties["ReturnString"].Value;
}
CB。の答え ちょっとした変更を加えて、私にとってはうまくいきました。 (C#とPowerShellに関して)これがどこにも投稿されていなかったので、投稿したいと思いました。
PowerShellスクリプトでHashtableを作成し、その中に2つの値(ブール値とInt)を保存し、それを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
そして、C#コードでCBと同じことをしました。しましたが、値を正常に戻すためにConvert.ToString
を使用する必要がありました。
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;)
}
次のStackOverflowの投稿でこれに対する答えを見つけました: https://stackoverflow.com/a/55775
Kieren Johnstoneのコメント:
(double)valueではなくConvert.ToDouble(value)を使用します。オブジェクトを受け取り、要求したすべてのタイプをサポートします! :)
いい質問だ!私は私の頭の上からショットを取ります...
2つの間でデータを受け渡すために使用する構造を表すC#のクラスを設計できます。 PSスクリプトでは、XmlWriterを使用してXML応答を作成し、Write-output
は、XML文字列を吐き出します。
C#側で、標準出力の応答をキャプチャし、XMLを新しい応答クラスに逆シリアル化し、結果を処理します。 XMLレスポンス以外にはstdoutに何も書き込めないことに注意してください。そうしないと、クラスにデシリアライズできません。