[Android Software/Hacking General [Developers Only]] k1ll3r8e:
Heyho,

1st of all, you should create a single function which starts the process for you. (This will make it a lot easier to maintain) For example, you could do like:

#region StartProcess

///<summary>
/// Executes a single command in an hidden process window and wait the given time (ms) for output before it ends.
///<para/>Uses <see cref="Process"/>
///<para/>*NOTE*
///<para/>timeOut = -1 implies infinite
///</summary>
///<param name="binary">Executable (c:\path\to\adb.exe)</param>
///<param name="args">Process arguments (shell ls-l)</param>
///<param name="responseEventHandler"><see cref="DataReceivedEventHandler"/></param>
///<param name="cancellationToken"><see cref="CancellationToken"/></param>
///<param name="timeout">Defines the time in ms the process will wait before it closes if no output returs, -1 implies infinite.</param>
///<exception cref="ArgumentNullException"/>
///<exception cref="FileNotFoundException"/>
///<returns><see cref="IEnumerable{String}"/></returns>
public static IEnumerable<string> StartProcess(string binary, string args, DataReceivedEventHandler responseEventHandler, CancellationToken cancellationToken, int timeout = -1)
{
if (string.IsNullOrEmpty(binary)) throw new ArgumentNullException(nameof(binary), "The provided string is NULL or empty");
if (string.IsNullOrEmpty(args)) throw new ArgumentNullException(nameof(args), "The provided string is NULL or empty");
if (binary != "cmd.exe" && !File.Exists(binary)) throw new FileNotFoundException("The provided executable could not be found", binary);

List<string> res = new List<string>();
using (Process proc = new Process()
{
StartInfo = new ProcessStartInfo
{
Arguments = Encoding.Default.GetString(Encoding.UTF8.GetBytes(args)),
CreateNoWindow = true,
FileName = binary,
RedirectStandardError = true,
RedirectStandardOutput = true,
StandardErrorEncoding = Encoding.UTF8,
StandardOutputEncoding = Encoding.UTF8,
UseShellExecute = false
}
})
{
proc.ErrorDataReceived += (s, e) =>
{
if (e.Data != null)
{
lock (res)
{
res.Add(e.Data);
}
responseEventHandler?.Invoke(s, e);
}
};
proc.OutputDataReceived += (s, e) =>
{
if (e.Data != null)
{
lock (res)
{
res.Add(e.Data);
}
responseEventHandler?.Invoke(s, e);
}
};
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
using (cancellationToken.Register(() =>
{
if (!proc.HasExited)
{
proc.Kill();
}
}))
{
if (proc.WaitForExit(timeout) && !cancellationToken.IsCancellationRequested)
{
return res;
}
if (!proc.HasExited)
{
proc.Kill();
}
}
}
return Enumerable.Empty<string>();
}
#endregion

This can then be used like:

(Note: This will block the current thread until the process is done!)

public void FlashBootImg(string imgPath)
{
// Clear the box
rtb.Document.Blocks.Clear();

// Start the process
StartProcess("Path/to/fastboot.exe", string.Concat("flash boot \"", imgPath, "\""), (s, e) =>
{
// Write the data to the text box
Application.Current?.Dispatcher.Invoke(() =>
{
rtb.Document.Blocks.Add(new Paragraph(new Run(e.Data)));
});
}, CancellationToken.None);
}

To avoid the blocking, you can do something like:

public void FlashBootImg(string imgPath)
{
// Clear the box
rtb.Document.Blocks.Clear();

// Start a new task
Task.Factory.StartNew(() =>
{
// Start the process
StartProcess("Path/to/fastboot.exe", string.Concat("flash boot \"", imgPath, "\""), (s, e) =>
{
// Write the data to the text box
Application.Current?.Dispatcher.Invoke(() =>
{
rtb.Document.Blocks.Add(new Paragraph(new Run(e.Data)));
});
}, CancellationToken.None);
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
}

You've also to reference the following namespaces:

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;

Hope this helps

Regards,

Sebastian