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

本文关键字:返回 PowerShell 执行 代码 一个对象 | 更新日期: 2023-09-27 18:30:49

某些 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;
  }

通过使用写入输出并依靠诸如"最后两个psObjects是我正在寻找的值"之类的约定,我已经设法通过一些黑客方式来做到这一点,但它很容易中断。

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

在你的Powershell脚本中,你可以根据需要构建一个哈希表:

[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.

如果要使用 PsCustomobject,如 Powershell v2.0 中的 Keith Hill 注释:

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脚本中,我创建了一个哈希表,在其中存储了2个值(布尔值和整数),然后将其转换为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

基伦·约翰斯通说:

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

哇,好问题!我会从我的头顶上开一枪...

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

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

对于PowerShell v3.0及更高版本,它甚至更简单:

$myObject = [PSCustomObject]@{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}
$myObject.Name = 'Mark'
return $myObject