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

Kje*_*sen 31 c# powershell

一些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"};
Run Code Online (Sandbox Code Playgroud)

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;
  }
Run Code Online (Sandbox Code Playgroud)

我设法做到这一点是一些hacky方式通过使用Write-Output并依赖于"最后两个psObjects是我正在寻找的值"的约定,但它会很容易打破.

CB.*_*CB. 30

在您的powershell脚本中,您可以根据需要构建Hashtable:

[hashtable]$Return = @{} 
$Return.ReturnCode = [int]1 
$Return.ReturnString = [string]"All Done!" 
Return $Return 
Run Code Online (Sandbox Code Playgroud)

在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.
Run Code Online (Sandbox Code Playgroud)

如果你想在PowerShell v2.0中的Keith Hill评论中使用PsCustomobject:

powershell脚本:

$return = new-object psobject -property @{ReturnCode=1;ReturnString="all done"}
$return
Run Code Online (Sandbox Code Playgroud)

c#代码:

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

  • @vittore是的,实际上在V3上使用pscustomobject` $ return = new-object psobject -property @ {ReturnCode = 1; Result ="all done"}`和C#4的动态关键字应该更容易.雅知道,因为V3现在基于DLR. (2认同)

hva*_*an3 5

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
Run Code Online (Sandbox Code Playgroud)

然后在我的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;)
   }
Run Code Online (Sandbox Code Playgroud)

我通过以下StackOverflow帖子找到了答案:https://stackoverflow.com/a/5577500

Kieren Johnstone说:

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