/// <summary> /// Starts a process resource by specifying the name of an application and a set of command-line arguments. /// </summary> /// <param name="processContext">The process context of an application file to run in the process.</param> /// <param name="processCompletedCallback">The process completed callback, invoked only when the process is started successfully and completed.</param> /// <exception cref="ArgumentNullException">The <paramref name="processContext"/> is <c>null</c>.</exception> /// <exception cref="Win32Exception">An error occurred when opening the associated file.</exception> public virtual void StartProcess(ProcessContext processContext, ProcessCompletedDelegate processCompletedCallback = null) { var task = RunAsync(processContext); if (processCompletedCallback != null) { task.ContinueWith(x => processCompletedCallback(task.Result.ExitCode)); } }
/// <summary> /// Starts a process and returns an awaitable task which will end once the application is closed. /// </summary> /// <param name="processContext">The process context of an application file to run in the process.</param> /// <returns>The <see cref="ProcessResult"/> containing details about the execution.</returns> /// <exception cref="ArgumentNullException">The <paramref name="processContext"/> is <c>null</c>.</exception> public virtual async Task <ProcessResult> RunAsync(ProcessContext processContext) { Argument.IsNotNull(nameof(processContext), processContext); Argument.IsNotNullOrWhitespace(nameof(processContext.FileName), processContext.FileName); var fileName = processContext.FileName; var arguments = processContext.Arguments; if (arguments == null) { arguments = string.Empty; } var tcs = new TaskCompletionSource <int>(); Log.Debug($"Running '{processContext.FileName}'"); try { #if NETFX_CORE var launcher = Launcher.LaunchUriAsync(new Uri(fileName)); if (processCompletedCallback != null) { launcher.Completed += (sender, e) => tcs.SetResult(0); } #else var processStartInfo = new ProcessStartInfo(fileName, arguments) { Verb = processContext.Verb }; if (!string.IsNullOrWhiteSpace(processContext.WorkingDirectory)) { processStartInfo.WorkingDirectory = processContext.WorkingDirectory; } var process = Process.Start(processStartInfo); process.EnableRaisingEvents = true; process.Exited += (sender, e) => tcs.SetResult(process.ExitCode); #endif } catch (Exception ex) { Log.Error(ex, $"An error occurred while running '{processContext.FileName}'"); tcs.SetException(ex); } await tcs.Task; return(new ProcessResult(processContext) { ExitCode = tcs.Task.Result }); }
/// <summary> /// Starts a process and returns an awaitable task which will end once the application is closed. /// </summary> /// <param name="processContext">The process context of an application file to run in the process.</param> /// <returns>The <see cref="ProcessResult"/> containing details about the execution.</returns> /// <exception cref="ArgumentNullException">The <paramref name="processContext"/> is <c>null</c>.</exception> public virtual async Task <ProcessResult> RunAsync(ProcessContext processContext) { Argument.IsNotNull(nameof(processContext), processContext); Argument.IsNotNullOrWhitespace(nameof(processContext.FileName), processContext.FileName); var fileName = processContext.FileName; var arguments = processContext.Arguments; if (arguments is null) { arguments = string.Empty; } var tcs = new TaskCompletionSource <int>(); Log.Debug($"Running '{processContext.FileName}'"); try { #if UWP await Launcher.LaunchUriAsync(new Uri(fileName)); #else var processStartInfo = new ProcessStartInfo(fileName, arguments) { Verb = processContext.Verb, UseShellExecute = processContext.UseShellExecute }; // Note for debuggers: whenever you *inspect* processStartInfo *and* use UseShellExecute = true, // the debugger will evaluate the Environment and EnvironmentVariables properties and instantiate them. // This will result in Process.Start to throw exceptions. The solution is *not* to inspect processStartInfo // when UseShellExecute is true if (!string.IsNullOrWhiteSpace(processContext.Verb) && !processStartInfo.UseShellExecute) { Log.Warning($"Verb is specified, this requires UseShellExecute to be set to true"); processStartInfo.UseShellExecute = true; } if (!string.IsNullOrWhiteSpace(processContext.WorkingDirectory)) { processStartInfo.WorkingDirectory = processContext.WorkingDirectory; } var process = Process.Start(processStartInfo); if (process is null) { Log.Debug($"Process is already completed, cannot wait for it to complete"); tcs.SetResult(0); } else { process.EnableRaisingEvents = true; process.Exited += (sender, e) => tcs.SetResult(process.ExitCode); } #endif } catch (Exception ex) { Log.Error(ex, $"An error occurred while running '{processContext.FileName}'"); tcs.SetException(ex); } await tcs.Task; return(new ProcessResult(processContext) { ExitCode = tcs.Task?.Result ?? 0 }); }