我正在创建一个需要与PowerShell交互的C#/ WPF应用程序(基本上,运行命令和脚本)。创建流程并启动它并不是一个问题,这很容易,但是当目标是在没有任何脚本的情况下启动它并使其在以后运行命令和脚本时变得更加困难:
我尝试了多种解决方案。
使用System.Diagnostics.Process
类,我可以启动该进程,让它运行,但即使我重定向流,写入stdin也不起作用:
var startInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
Arguments = "-ExecutionPolicy Bypass -NoLogo -NoExit",
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};
_ps = new Process()
{
EnableRaisingEvents = true,
StartInfo = startInfo
};
_ps.Start();
[...]
_ps.StandardInput.WriteLine(TextBox_Input.Text); // No effect
使用System.Management.Automation.PowerShell
类并不是更好,我可以准备管道(添加要执行的脚本),调用它,但是,我不能在以后运行脚本来保持进程活着。
我需要尽快启动该过程,以便能够以更快的速度发送命令并运行它们(并避免可能导致延迟的进程启动)。
答案 0 :(得分:3)
如评论中所述,在应用程序启动时设置(并打开)一个运行空间:
Runspace rs;
public MainWindow()
{
InitializeComponent();
rs = RunspaceFactory.CreateRunspace();
rs.Open();
}
现在,您只需要一个创建PowerShell
实例并在运行空间中执行它的函数:
private Collection<PSObject> RunScript(string script)
{
using(PowerShell ps = PowerShell.Create())
{
ps.AddScript(script);
ps.Runspace = rs;
return ps.Invoke();
}
}
然后,在用户运行脚本输入的事件处理程序中:
private void button_Click(object sender, RoutedEventArgs e)
{
Collection<PSObject> returnedObjects = RunScript(TextBox_Input.Text);
// do what you want with returnedObjects if necessary
}
这当然是一个过于简化的例子。在真实世界的应用程序中,您将检查error and warning streams,使用APM(BeginInvoke()
/ EndInvoke()
)等。