Last active
September 16, 2016 02:32
-
-
Save jeremybeavon/0016e8f4aa4ba6ca937178e4caa0c308 to your computer and use it in GitHub Desktop.
Powershell cmdlet that prints outs output as it happens
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Management.Automation; | |
using System.Threading; | |
[Cmdlet(VerbsLifecycle.Invoke, "Process")] | |
public sealed class InvokeProcessCommand : Cmdlet | |
{ | |
private bool isProcessFinishedOrTimedOut; | |
public InvokeProcessCommand() | |
{ | |
TimeoutMinutes = 60; | |
} | |
[Parameter(Mandatory = true)] | |
public string CommandName { get; set; } | |
[Parameter(Mandatory = true)] | |
public string ArgumentList { get; set; } | |
[Parameter] | |
public int TimeoutMinutes { get; set; } | |
protected override void ProcessRecord() | |
{ | |
WriteObject(StartProcessInfo()); | |
} | |
private bool StartProcessInfo() | |
{ | |
using (Process process = new Process() | |
{ | |
StartInfo = new ProcessStartInfo() | |
{ | |
FileName = CommandName, | |
Arguments = ArgumentList, | |
RedirectStandardError = true, | |
RedirectStandardOutput = true, | |
UseShellExecute = false, | |
CreateNoWindow = true | |
} | |
}) | |
{ | |
Queue<string> messages = new Queue<string>(); | |
using (AutoResetEvent waitHandle = new AutoResetEvent(false)) | |
{ | |
DataReceivedEventHandler dataHandler = (sender, args) => | |
{ | |
if (args.Data != null) | |
{ | |
lock (messages) | |
{ | |
messages.Enqueue(args.Data); | |
} | |
waitHandle.Set(); | |
} | |
}; | |
process.OutputDataReceived += dataHandler; | |
process.ErrorDataReceived += dataHandler; | |
if (!process.Start()) | |
{ | |
WriteVerbose("Failed to start process: " + CommandName); | |
return false; | |
} | |
try | |
{ | |
process.BeginErrorReadLine(); | |
process.BeginOutputReadLine(); | |
WriteVerbose("Successfull started process" + CommandName); | |
WriteVerbose(string.Format("Process will time-out after {0} minutes.", TimeoutMinutes)); | |
WriteVerbose("Starting at " + DateTime.Now); | |
bool hasExitCode = false; | |
new Thread(() => | |
{ | |
hasExitCode = process.WaitForExit(TimeoutMinutes * 60 * 1000); | |
isProcessFinishedOrTimedOut = true; | |
waitHandle.Set(); | |
}).Start(); | |
WaitForExit(messages, waitHandle); | |
if (hasExitCode) | |
{ | |
WriteVerbose("Finished at " + DateTime.Now); | |
if (process.ExitCode == 0) | |
{ | |
WriteVerbose("Process has completed successfully."); | |
} | |
else | |
{ | |
WriteVerbose("Process failed. ExitCode = " + process.ExitCode); | |
return false; | |
} | |
} | |
else | |
{ | |
WriteVerbose(string.Format("{0} has not completed after {1} minutes - please investigate!", CommandName, TimeoutMinutes)); | |
process.Kill(); | |
return false; | |
} | |
} | |
catch (Exception exception) | |
{ | |
WriteVerbose("Exception: " + exception); | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
private void WaitForExit(Queue<string> messages, WaitHandle handle) | |
{ | |
while (true) | |
{ | |
WriteMessages(messages); | |
if (isProcessFinishedOrTimedOut) | |
{ | |
WriteMessages(messages); | |
return; | |
} | |
handle.WaitOne(TimeSpan.FromMinutes(TimeoutMinutes)); | |
} | |
} | |
private void WriteMessages(Queue<string> messages) | |
{ | |
lock (messages) | |
{ | |
while (messages.Count != 0) | |
{ | |
WriteVerbose(messages.Dequeue()); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment