34

一些 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 并依赖诸如“最后两个 psObjects 是我正在寻找的值”之类的约定,我设法做到了这一点,但它很容易破坏。

4

3 回答 3

35

In your powershell script you can build an Hashtable based on your necessity:

[hashtable]$Return = @{} 
$Return.ReturnCode = [int]1 
$Return.ReturnString = [string]"All Done!" 
Return $Return 

In C# code handle the Psobject in this way

 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.

If you want to use a PsCustomobject as in Keith Hill comment in powershell v2.0:

powershell script:

$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;
   }
于 2012-04-11T15:08:52.457 回答
6

CB. 的回答对我来说非常有用,只需稍作改动。我没有在任何地方看到这个发布(关于 C# 和 PowerShell),所以我想发布它。

在我的 PowerShell 脚本中,我创建了一个 Hashtable,在其中存储了 2 个值(一个 Boolean 和一个 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)value。它接受一个对象并支持您要求的所有类型!:)

于 2014-10-02T16:58:14.257 回答
1

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

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

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

于 2012-04-11T13:14:55.467 回答