我正在创建一个MVC4 Web应用程序,该应用程序能够创建一个控制台,使用SignalR将Powershell脚本的输出记录到日志窗口。目前我最好的工作是Capturing Powershell output in C# after Pipeline.Invoke throws。问题是我无法使用此方法将实时输出流传递给客户端。脚本完成处理后,我只能输出输出。目前我正在尝试这个但是没有收到任何输出。
var loggingHub = new LoggingHub();
string powerShellExeLocation = null;
var localKey = Registry.LocalMachine;
var subKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine");
powerShellExeLocation = subKey.GetValue("ApplicationBase").ToString();
if (!Directory.Exists(powerShellExeLocation))
throw new Exception("Cannot locate the PowerShell dir.");
powerShellExeLocation = Path.Combine(powerShellExeLocation, "powershell.exe");
if (!File.Exists(powerShellExeLocation))
throw new Exception("Cannot locate the PowerShell executable.");
if (!File.Exists(scriptFile))
throw new Exception("Cannot locate the PowerShell script.");
var processInfo = new ProcessStartInfo
{
Verb = "runas",
UseShellExecute = false,
RedirectStandardOutput = true
};
processInfo.RedirectStandardOutput = true;
processInfo.WorkingDirectory = Environment.CurrentDirectory;
processInfo.FileName = powerShellExeLocation;
//processInfo.Arguments = "-NoLogo -OutputFormat Text -NonInteractive -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + scriptFile + "\" ";
processInfo.Arguments = build;
var powerShellProcess = new Process {StartInfo = processInfo};
powerShellProcess.Start();
while (!powerShellProcess.HasExited)
{
loggingHub.Send(DateTime.Now.ToString("h:mm:ss tt"), "info", powerShellProcess.StandardOutput.ReadLine());
}
答案 0 :(得分:1)
记录输出的一种方法是不仅托管PowerShell引擎,还要实现主机接口。然后,您将收到每个"写"到主持人"当PowerShell引擎处理脚本时。实现主机接口并不是一件容易的事,但它也不是太难。请查看此MSDN链接http://msdn.microsoft.com/en-us/windows/desktop/ee706584(v=vs.85)
答案 1 :(得分:1)
来自:
**当Process将文本写入其标准流时,该文本通常显示在控制台上。通过重定向StandardOutput流,您可以操纵或抑制进程的输出。例如,您可以过滤文本,以不同方式对其进行格式化,或将输出写入控制台和指定的日志文件。 注意 如果要将RedirectStandardOutput设置为true,则必须将UseShellExecute设置为false。否则,从StandardOutput流中读取会引发异常。
可以同步或异步读取重定向的StandardOutput流。 Read,ReadLine和ReadToEnd等方法对进程的输出流执行同步读取操作。在关联的Process写入其StandardOutput流或关闭流之前,这些同步读取操作不会完成。 相反,BeginOutputReadLine在StandardOutput流上启动异步读取操作。此方法为流输出启用指定的事件处理程序,并立即返回到调用程序,调用程序可以在将流输出定向到事件处理程序时执行其他工作。 注意 处理异步输出的应用程序应调用WaitForExit方法以确保已刷新输出缓冲区。
同步读取操作在从StandardOutput流读取调用者和写入该流的子进程之间引入依赖关系。这些依赖项可能会导致死锁条件。当调用者从子进程的重定向流中读取时,它依赖于子进程。调用者等待读操作,直到子进程写入流或关闭流。当子进程写入足够的数据来填充其重定向流时,它依赖于父进程。子进程等待下一个写操作,直到父进程从完整流中读取或关闭流。当调用者和子进程等待彼此完成操作时,将导致死锁条件,并且两者都不能继续。您可以通过评估调用者和子进程之间的依赖关系来避免死锁。**
这似乎解释了发生了什么。您是否尝试过使用BeginOutputReadLine方法而不是ReadLine?