private RunStatus RunVerifierExecutable(string fullExePath, StringLineReceived stdoutLineReceived, string args = null)
        {
            var outStatus = new RunStatus();
            using (var proc = new Process())
            {
                var startInfo = new ProcessStartInfo(fullExePath);
                if (!String.IsNullOrEmpty(args))
                    startInfo.Arguments = args;

                startInfo.CreateNoWindow = true;
                startInfo.UseShellExecute = false;

                if (stdoutLineReceived != null)
                {
                    startInfo.RedirectStandardOutput = true;
                    startInfo.StandardOutputEncoding = Encoding.UTF8;
                    proc.OutputDataReceived += (sender, dataArgs) => { stdoutLineReceived(sender, dataArgs.Data); };
                }
                else
                    startInfo.RedirectStandardOutput = false;

                startInfo.RedirectStandardError = true;
                startInfo.StandardErrorEncoding = Encoding.UTF8;
                proc.ErrorDataReceived += (sender, evt) =>
                {
                    if (outStatus.ErrorString == null)
                        outStatus.ErrorString = "";

                    if (evt.Data == null)
                    {
                        outStatus.ErrorString.TrimEnd('\r', '\n');
                        return;
                    }

                    outStatus.ErrorString += evt.Data;
                };

                proc.StartInfo = startInfo;
                proc.Start();

                if (startInfo.RedirectStandardOutput)
                    proc.BeginOutputReadLine();
                if (startInfo.RedirectStandardError)
                    proc.BeginErrorReadLine();

                proc.WaitForExit();

                if (startInfo.RedirectStandardError)
                    WaitForProcessEOF(proc, "error");
                if (startInfo.RedirectStandardOutput)
                    WaitForProcessEOF(proc, "output");

                outStatus.ExitCode = proc.ExitCode;
            }
            return outStatus;
        }
        private RunStatus RunCopierExecutable(string fullExePath, StringLineReceived stdoutLineReceived,
			IEnumerable<string> executableInput = null, bool runAsAdmin = false)
        {
            var outStatus = new RunStatus();
            using (var proc = new Process())
            {
                string clientGuidStr = Guid.NewGuid().ToString();
                ;
                var stdPipeSvr = new NamedPipeServerStream("Copier_" + clientGuidStr + "_data",
                    PipeDirection.InOut, 1, PipeTransmissionMode.Byte);
                var errPipeSvr = new NamedPipeServerStream("Copier_" + clientGuidStr + "_error",
                    PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

                proc.StartInfo = new ProcessStartInfo(fullExePath, clientGuidStr);
                proc.StartInfo.UseShellExecute = true;
                proc.StartInfo.CreateNoWindow = true;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                if (runAsAdmin)
                    proc.StartInfo.Verb = "runas";

                proc.Start();
                var endEvent = new AutoResetEvent(false);
                errPipeSvr.BeginWaitForConnection(iar =>
                {
                    var pipSvr = (NamedPipeServerStream) iar.AsyncState;
                    try
                    {
                        pipSvr.EndWaitForConnection(iar);
                        var errSb = new StringBuilder();

                        var readBuffer = new byte[4096];
                        pipSvr.BeginRead(readBuffer, 0, readBuffer.Length, iar2 =>
                        {
                            var pipeStr = (NamedPipeServerStream) iar2.AsyncState;
                            int numBytes = pipeStr.EndRead(iar2);

                            if (numBytes > 0)
                            {
                                string recvStr = Encoding.UTF8.GetString(readBuffer, 0, numBytes);
                                errSb.Append(recvStr);
                            }
                            else //EOF
                            {
                                outStatus.ErrorString = errSb.ToString().TrimEnd('\r', '\n');
                                pipeStr.Close();
                                endEvent.Set();
                            }
                        }, pipSvr);
                    }
                    catch (ObjectDisposedException)
                    {
                    } //happens if no connection happened
                }, errPipeSvr);

                stdPipeSvr.WaitForConnection();
                if (executableInput != null)
                {
                    var sw = new StreamWriter(stdPipeSvr, Encoding.UTF8);
                    foreach (string line in executableInput)
                        sw.WriteLine(line);

                    //last one to indicate no more input
                    sw.WriteLine();
                    sw.Flush();
                }
                stdPipeSvr.WaitForPipeDrain(); //wait for process to read all bytes we sent it

                using (var sr = new StreamReader(stdPipeSvr, Encoding.UTF8, false))
                {
                    while (stdPipeSvr.IsConnected)
                    {
                        string recvLine = sr.ReadLine();
                        if (stdoutLineReceived != null)
                            stdoutLineReceived(stdPipeSvr, recvLine);

                        if (recvLine == null)
                            break; //EOF
                    }

                    sr.Close(); //closes the underlying named pipe as well
                }

                proc.WaitForExit();
                outStatus.ExitCode = proc.ExitCode;
                if (outStatus.ExitCode != 0)
                    endEvent.WaitOne(); //wait for stderr to be read
            }
            return outStatus;
        }