2014-04-25 3 views
2

PowerRhell을 사용하여 PowerShell 스크립트의 출력을 로그 창에 기록하는 콘솔을 만들 수있는 MVC4 웹 응용 프로그램을 만들고 있습니다. 현재 내가 일한 것은 Capturing Powershell output in C# after Pipeline.Invoke throws입니다. 문제는이 방법을 사용하여 클라이언트에게 실시간 출력 스트림을 전달할 수 없다는 것입니다. 스크립트 처리가 완료되면 출력물을 공급할 수 있습니다. 현재 나는 이것을 시도하고 있지만 출력을받지 못하고있다.Powershell 스크립트의 출력 얻기

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()); 
} 

답변

1

발생하는 출력을 로그하는 한 가지 방법은 PowerShell 엔진을 호스트하는 것뿐 아니라 호스트 인터페이스도 구현하는 것입니다. 그런 다음 PowerShell 엔진이 스크립트를 처리 할 때마다 "호스트"에 "기록"할 때마다 다시 호출됩니다. 호스트 인터페이스를 구현하는 것은 사소한 것이 아니라 너무 어렵지 않습니다. 에서이 MSDN 링크 http://msdn.microsoft.com/en-us/windows/desktop/ee706584(v=vs.85)

1

에서보세요 :

http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx

을 ** 프로세스가 표준 스트림에 텍스트를 쓸 때, 텍스트는 일반적으로 콘솔에 표시됩니다. StandardOutput 스트림을 리디렉션하면 프로세스의 출력을 조작하거나 억제 할 수 있습니다. 예를 들어, 텍스트를 필터링하거나, 다르게 형식을 지정하거나, 콘솔과 지정된 로그 파일에 출력을 쓸 수 있습니다. 참고 RedirectStandardOutput을 true로 설정하려면 UseShellExecute를 false로 설정해야합니다. 그렇지 않은 경우, StandardOutput 스트림을 읽어 내면 (자) 예외가 슬로우됩니다.

리디렉션 된 StandardOutput 스트림을 동 기적 또는 비동기 적으로 읽을 수 있습니다. Read, ReadLine 및 ReadToEnd와 같은 메서드는 프로세스의 출력 스트림에 대한 동기 읽기 작업을 수행합니다. 이러한 동기 읽기 작업은 연결된 Process가 해당 StandardOutput 스트림에 쓰거나 스트림을 닫을 때까지 완료되지 않습니다. 대조적으로 BeginOutputReadLine은 StandardOutput 스트림에서 비동기 읽기 작업을 시작합니다. 이 메서드는 스트림 출력에 지정된 이벤트 처리기를 활성화하고 호출자에게 즉시 반환합니다. 호출자는 스트림 출력이 이벤트 처리기로 전달되는 동안 다른 작업을 수행 할 수 있습니다. 참고 비동기 출력을 처리하는 응용 프로그램은 WaitForExit 메서드를 호출하여 출력 버퍼가 플러시되었는지 확인해야합니다.

동기 읽기 작업은 호출자가 StandardOutput 스트림에서 읽는 것과 해당 스트림에 쓰는 하위 프로세스간에 종속성을 도입합니다. 이러한 종속성으로 인해 교착 상태가 발생할 수 있습니다. 호출자가 하위 프로세스의 리디렉션 된 스트림에서 읽으면 자식에 종속됩니다. 호출 측은, 아이가 스트림에 기입하는지, 스트림을 닫을 때까지, read 오퍼레이션을 대기합니다. 하위 프로세스가 리디렉션 된 스트림을 채우기에 충분한 데이터를 쓰면 부모 프로세스에 종속됩니다. 자식 프로세스는 부모가 전체 스트림을 읽거나 스트림을 닫을 때까지 다음 쓰기 작업을 기다립니다. 교착 상태 조건은 호출자와 자식 프로세스가 서로 작업을 완료하기 위해 대기하고 둘 다 계속할 수 없게 될 때 발생합니다. 호출자와 하위 프로세스 간의 종속성을 평가하여 교착 상태를 피할 수 있습니다. **

이는 무슨 일이 일어나는지를 설명하는 것 같습니다. ReadLine 대신 BeginOutputReadLine 메서드를 사용해 보셨습니까?