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

如何从PowerShell返回一个对象或多个值以执行C#代码,c#,powershell,C#,Powershell,一些C#代码执行带有参数的powershell脚本。我想从Powershell获取返回代码和字符串,以了解Powershell脚本中是否一切正常 在Powershell和C中,正确的方法是什么# 动力壳 C# void RunPowershellScript(字符串脚本文件,列表参数) { RunspaceConfiguration RunspaceConfiguration=RunspaceConfiguration.Create(); 使用(Runspace Runspace=Runspac

一些C#代码执行带有参数的powershell脚本。我想从Powershell获取返回代码和字符串,以了解Powershell脚本中是否一切正常

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

动力壳 C#
void RunPowershellScript(字符串脚本文件,列表参数)
{
RunspaceConfiguration RunspaceConfiguration=RunspaceConfiguration.Create();
使用(Runspace Runspace=RunspaceFactory.CreateRunspace(runspaceConfiguration))
{
Open();
RunspaceInvoke scriptInvoker=新的RunspaceInvoke(运行空间);
Pipeline Pipeline=runspace.CreatePipeline();
命令scriptCommand=新命令(脚本文件);
Collection commandParameters=new Collection();
foreach(参数中的字符串scriptParameter)
{
CommandParameter commandParm=新CommandParameter(null,scriptParameter);
commandParameters.Add(commandParm);
scriptCommand.Parameters.Add(commandParm);
}
pipeline.Commands.Add(scriptCommand);
对象集合;
psObjects=pipeline.Invoke();
//在这里做什么?
//ReturnInfo ReturnInfo=pipeline.DoMagic();
}
}
类返回信息
{
公共代码;
公共字符串返回文本;
}

通过使用写输出和依赖“最后两个PSObject是我要寻找的值”等约定,我成功地做到了这一点,但它很容易崩溃。

哇,好问题!我会在头顶上开一枪

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


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

在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.
如果要使用powershell v2.0中Keith Hill注释中的PsCustomobject:

powershell脚本:

$return = new-object psobject -property @{ReturnCode=1;ReturnString="all done"}
$return
c#代码:

只做了一点小小的改变,对我来说效果很好。我没有在任何地方看到这篇文章(关于C#和PowerShell),所以我想发布它

在我的PowerShell脚本中,我创建了一个哈希表,在其中存储了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帖子找到了答案:

Kieren Johnstone说:

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


正如您所准备的那样,
Invoke
返回一个包含管道输出的对象数组。如果管道没有输出,则返回emptycollection。所以我不确定你期望什么。。。你是在问如何调整你的powershell以返回你期望的值吗?Joshua Drake>>我在powershell脚本注释中添加了一点c,我希望这能让它更清楚,我想要什么。:)需要帮忙吗?约书亚·德雷克>>会的!现在我只需要找出另一半——如何从C#code中读取它。你应该能够在调试器中检查
psObjects
,看看你是否有一些通用字典对象,或者具有特定结构的对象,然后解决这个问题。这样,你不仅可以设置任何类的字段hashtable@vittore对事实上,在V3上,使用pscustomobject
$return=new-object-psobject-property@{ReturnCode=1;Result=“all done”}
和C#4的动态关键字应该会更容易。你知道,因为V3现在是基于DLR的。如果PowerShell脚本实例调用Write Host,则ImmediateBaseObject为null。模式匹配应在C#中使用。示例:如果(p.ImmediateBaseObject是哈希表ht){…}
ReturnInfo ri = new ReturnInfo();
foreach (PSObject p in psObjects)
   {
     ri.ReturnCode = (int)p.Properties["ReturnCode"].Value;
     ri.ReturnText = (string)p.Properties["ReturnString"].Value;
   }
$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
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;)
   }