某些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"};
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;,但它会很容易破坏。
答案 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#code:
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#端,捕获标准输出响应,将XML反序列化为新的响应类,然后处理结果。请注意,除了XML响应之外,您不能向stdout写任何内容,否则您将无法反序列化到该类中。