如何将一个或多个值从PowerShell返回到执行C#代码

时间:2012-04-11 12:48:27

标签: c# powershell

某些C#代码使用参数执行powershell脚本。我想从Powershell获取一个返回码和一个字符串,以便知道如果Powershell脚本中的所有内容都正常。

在Powershell和C#中,正确的方法是什么?

Powershell的

# 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;
  }

我设法做到这一点是一些hacky方式,使用Write-Output并依赖于&#34这样的约定;最后两个psObjects是我正在寻找的值&#34;,但它会很容易破坏。

3 个答案:

答案 0 :(得分:27)

在您的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#c​​ode:

ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
   {
     ri.ReturnCode = (int)p.Properties["ReturnCode"].Value;
     ri.ReturnText = (string)p.Properties["ReturnString"].Value;
   }

答案 1 :(得分:5)

CB.'s answer只为我做了很小的改动。我没有看到这张贴在任何地方(关于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/5577500

Kieren Johnstone说:

  

使用Convert.ToDouble(value)而不是(double)值。需要一个   对象并支持您要求的所有类型! :)

答案 2 :(得分:0)

哇,好问题!我会从头顶射击......

您可以在C#中设计一个类,表示您希望用于在两者之间传递数据的结构。在PS脚本中,您可以使用XmlWriter来制作XML响应并使用Write-output来吐出XML字符串。

在C#端,捕获标准输出响应,将XM​​L反序列化为新的响应类,然后处理结果。请注意,除了XML响应之外,您不能向stdout写任何内容,否则您将无法反序列化到该类中。