c# - 无法将 .Net 中的对象通过管道传输到托管的 powershell
问题描述
我想Powershell
在应用程序中执行脚本C#
。为此,我正在使用Microsoft.PowerShell.5.ReferenceAssemblies
包(由于net48
要求)。
我想将对象从管道.Net
传输到脚本但没有成功。
static void Main(string[] args)
{
var runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
var ps = PowerShell.Create();
ps.Runspace = runspace;
var pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(@"example.ps1");
pipeline.Input.Write("1");
pipeline.Input.Write("2");
pipeline.Input.Flush();
var res = pipeline.Invoke();
foreach (var xx in res) {
Console.WriteLine(xx);
}
}
示例.ps1:
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline=$true)]
$p
)
Begin {
Write-Output "Start"
}
Process {
Write-Output "Process $_"
}
End {
Write-Output "End"
}
实际输出:
Start
Process
End
预期输出:
Start
Process 1
Process 2
End
解决方案
经过大量的经验测试,我发现以下对我有用:
pipeline.Input.Write("1");
pipeline.Input.Write("2");
pipeline.Commands.Add(".\\example.ps1");
也就是说,使用pipeline.Commands.Add
,而不是pipeline.Commands.AddScript
。即使您的命令是脚本文件的名称,它也是命令而不是脚本!
另外,请注意,在pipeline.Input.Write
之前pipeline.Commands.Add
,我已经删除了pipeline.Input.Flush()
- 这些似乎都以不同的方式破坏了事物。
完整代码变为:
static void Main(string[] args)
{
var runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
var ps = PowerShell.Create();
ps.Runspace = runspace;
var pipeline = runspace.CreatePipeline();
pipeline.Input.Write("1");
pipeline.Input.Write("2");
pipeline.Commands.Add(".\\example.ps1");
var res = pipeline.Invoke();
foreach (var xx in res) {
Console.WriteLine(xx);
}
}
应用程序将其写入控制台:
Start
Process 1
Process 2
End
推论是,它看起来AddScript
不消耗管道输入。
为了完整起见,这是我在此过程中所做的其他一些(损坏的)测试:
// fails - original code
//pipeline.Commands.AddScript(".\\example.ps1");
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
//pipeline.Input.Flush();
// Start
// Process
// End
// test - works for a command, but requires in-script parameters
//pipeline.Commands.AddScript("1, 2 | write-output");
// 1
// 2
// test - works for a script, but requires in-script parameters
//pipeline.Commands.AddScript("1, 2 | .\\example.ps1");
// Start
// Process 1
// Process 2
// End
// test - works for a command with pipeline input
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
//pipeline.Commands.Add("write-output");
// 1
// 2
// test - fails with AddScript and mandatory parameters on script
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
//pipeline.Commands.AddScript("write-output");
// System.Management.Automation.ParameterBindingException: 'Cannot process command because of one
// or more missing mandatory parameters: InputObject.'
// test - fails with AddScript and optional parameters on script
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
//pipeline.Commands.AddScript(".\\example.ps1");
// Start
// Process
// End
// fails - flush kills pipelne
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
//pipeline.Input.Flush();
//pipeline.Commands.Add(".\\example.ps1");
// Start
// Process
// End
// fails - pipeline written after script
//pipeline.Commands.AddScript(".\\example.ps1");
//pipeline.Input.Write("1");
//pipeline.Input.Write("2");
// Start
// Process
// End
更新
您可以将包含 PowerShell 脚本的字符串转换为“可流水线”命令,如下所示(注意new Command
- ie中的第二个参数isScript: true
):
pipeline.Input.Write("1");
pipeline.Input.Write("2");
var scriptText = File.ReadAllText(".\\example.ps1");
pipeline.Commands.Add(
new Command(scriptText, true)
);
// Start
// Process 1
// Process 2
// End
推荐阅读
- postgresql - 是否可以在 Postgres INSERT 中声明和使用 $1、$2 等值?
- android - 如何发送 Multipart.Part 意图
- c - 调用使用命令行参数的函数
- typescript - 是否可以使用 for 循环内的条件缩短打字稿中的三元运算符
- elasticsearch - 在 LogStash 中,如何删除任何大于特定大小的 json/xml 字段
- java - WildFly:此 URL 不支持 HTTP 方法 POST
- r - 如何聚合数据框并通过 r 中的重复行对列的值求和
- iframe - 功能策略 Safari - iframes - Youtube - ReactJS
- android - 单击抽屉导航项时尝试使用 NavGraph 执行方法
- java - 转换异常:HttpsURLConnectionOldImpl v javax.net.ssl.HttpsURLConnection