web-dev-qa-db-ja.com

PowerShellからC#コードの実行にオブジェクトまたは複数の値を返す方法

一部の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"};

C#

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は私が探している値です」などの規則に依存することで、これをなんとかしてやっかいな方法にしていますが、簡単に壊れてしまいます。

31
Kjensen

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;
   }
29
CB.

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)を使用します。オブジェクトを受け取り、要求したすべてのタイプをサポートします! :)

5
hvaughan3

いい質問だ!私は私の頭の上からショットを取ります...

2つの間でデータを受け渡すために使用する構造を表すC#のクラスを設計できます。 PSスクリプトでは、XmlWriterを使用してXML応答を作成し、Write-outputは、XML文字列を吐き出します。

C#側で、標準出力の応答をキャプチャし、XMLを新しい応答クラスに逆シリアル化し、結果を処理します。 XMLレスポンス以外にはstdoutに何も書き込めないことに注意してください。そうしないと、クラスにデシリアライズできません。

0
mgnoonan