public void SetUp() { terminatedSuccessfully = new ManualResetEvent(false); processTask = Tasks.StartProcessTask(Path.Combine(Environment.SystemDirectory, "cmd.exe"), "/C exit " + COR_E_STACKOVERFLOW, Environment.CurrentDirectory); processTask.Terminated += processTask_Terminated; processTask.Start(); Assert.IsTrue(processTask.Join(TimeSpan.FromSeconds(10)), "Wait for exit"); }
/// <inheritdoc /> public IVisualStudio LaunchVisualStudio(VisualStudioVersion version, ILogger logger) { if (logger == null) throw new ArgumentNullException("logger"); Pair<string, VisualStudioVersion>? installDirAndVersion = GetVisualStudioInstallDirAndVersion(version); if (!installDirAndVersion.HasValue) { logger.Log(LogSeverity.Debug, string.Format("Could not find Visual Studio version '{0}'.", version)); return null; } string devenvPath = Path.Combine(installDirAndVersion.Value.First, "devenv.exe"); ProcessTask devenvProcessTask = new ProcessTask(devenvPath, "", Environment.CurrentDirectory); logger.Log(LogSeverity.Debug, string.Format("Launching Visual Studio using path: '{0}'.", devenvProcessTask.ExecutablePath)); devenvProcessTask.Start(); System.Diagnostics.Process devenvProcess = devenvProcessTask.Process; if (devenvProcess != null) { int processId = devenvProcess.Id; Stopwatch stopwatch = Stopwatch.StartNew(); for (;;) { IVisualStudio visualStudio = GetVisualStudioFromProcess(processId, installDirAndVersion.Value.Second, true, logger); if (visualStudio != null) return visualStudio; if (stopwatch.ElapsedMilliseconds > VisualStudioAttachTimeoutMilliseconds) { logger.Log(LogSeverity.Debug, string.Format("Stopped waiting for Visual Studio to launch after {0} milliseconds.", VisualStudioAttachTimeoutMilliseconds)); break; } if (!devenvProcessTask.IsRunning) break; Thread.Sleep(500); } } if (devenvProcessTask.IsTerminated && devenvProcessTask.Result != null) { if (! devenvProcessTask.Result.HasValue) logger.Log(LogSeverity.Debug, "Failed to launch Visual Studio.", devenvProcessTask.Result.Exception); } return null; }
private void FreeResources(bool abortImmediately) { if (processTask != null) { if (! abortImmediately) { if (!processTask.Join(JoinBeforeAbortWarningTimeout)) { Logger.Log(LogSeverity.Info, "Waiting for the host process to terminate."); if (!processTask.Join(JoinBeforeAbortTimeout - JoinBeforeAbortWarningTimeout)) Logger.Log(LogSeverity.Info, string.Format("Timed out after {0} minutes.", JoinBeforeAbortTimeout.TotalMinutes)); } } if (! processTask.Join(TimeSpan.Zero)) { Logger.Log(LogSeverity.Warning, "Forcibly killing the host process!"); processTask.Abort(); processTask.Join(JoinAfterAbortTimeout); } processTask = null; } if (clientChannel != null) { clientChannel.Dispose(); clientChannel = null; } if (callbackChannel != null) { callbackChannel.Dispose(); callbackChannel = null; } if (temporaryConfigurationFilePath != null) { File.Delete(temporaryConfigurationFilePath); temporaryConfigurationFilePath = null; } lock (logConsoleOutputBufferTimer) { logConsoleOutputBufferTimer.Dispose(); } }
private void StartProcess(string hostConnectionArguments) { bool useElevation = HostSetup.Elevated && !DotNetRuntimeSupport.IsUsingMono; CreateTemporaryConfigurationFile(); StringBuilder hostArguments = new StringBuilder(); hostArguments.Append(hostConnectionArguments); if (HostSetup.DebuggerSetup == null) hostArguments.Append(@" /timeout:").Append((int)WatchdogTimeout.TotalSeconds); hostArguments.Append(@" /owner-process:").Append(Process.GetCurrentProcess().Id); if (HostSetup.ApplicationBaseDirectory != null) hostArguments.Append(@" /application-base-directory:""").Append( FileUtils.StripTrailingBackslash(HostSetup.ApplicationBaseDirectory)).Append('"'); foreach (string hintDirectory in HostSetup.HintDirectories) hostArguments.Append(@" /hint-directory:""").Append( FileUtils.StripTrailingBackslash(hintDirectory)).Append('"'); hostArguments.Append(@" /configuration-file:""").Append(temporaryConfigurationFilePath).Append('"'); if (HostSetup.ShadowCopy) hostArguments.Append(@" /shadow-copy"); if (HostSetup.DebuggerSetup != null) hostArguments.Append(@" /debug"); hostArguments.Append(" /severity-prefix"); if (useElevation) hostArguments.Append(" /quiet"); severityPrefixParser = new SeverityPrefixParser(); processTask = CreateProcessTask(GetInstalledHostProcessPath(), hostArguments.ToString(), HostSetup.WorkingDirectory ?? Environment.CurrentDirectory); processTask.Terminated += HandleProcessExit; if (useElevation) { if (HostSetup.RuntimeVersion != null) throw new HostException("The host does not support a non-default RuntimeVersion with Elevation."); processTask.UseShellExecute = true; processTask.ConfigureProcessStartInfo += (sender, e) => { e.ProcessStartInfo.Verb = "runas"; e.ProcessStartInfo.ErrorDialog = true; e.ProcessStartInfo.ErrorDialogParentHandle = GetOwnerWindowHandle(); }; } else { processTask.CaptureConsoleOutput = true; processTask.CaptureConsoleError = true; processTask.ConsoleOutputDataReceived += LogConsoleOutput; processTask.ConsoleErrorDataReceived += LogConsoleError; // Force CLR runtime version. string runtimeVersion = HostSetup.RuntimeVersion; if (runtimeVersion == null) runtimeVersion = DotNetRuntimeSupport.MostRecentInstalledDotNetRuntimeVersion; if (!runtimeVersion.StartsWith("v")) runtimeVersion = "v" + runtimeVersion; // just in case, this is a common user error // http://msdn.microsoft.com/en-us/library/w4atty68.aspx if (runtimeVersion == "v4.0") runtimeVersion = "v4.0.30319"; processTask.SetEnvironmentVariable("COMPLUS_Version", runtimeVersion); } processTask.Start(); }
private static void ConfigureProcessTaskForLogging(ProcessTask task, MarkupStreamWriter writer) { task.Started += delegate { writer.BeginSection(String.Format("Run Process: {0} {1}", task.ExecutablePath, task.Arguments)); writer.WriteLine("Working Directory: {0}", task.WorkingDirectory); writer.BeginMarker(Marker.Monospace); }; task.ConsoleOutputDataReceived += delegate(object sender, DataReceivedEventArgs e) { if (e.Data != null) writer.WriteLine(e.Data); }; task.ConsoleErrorDataReceived += delegate(object sender, DataReceivedEventArgs e) { if (e.Data != null) writer.WriteLine(e.Data); }; task.Aborted += delegate { if (task.IsRunning) writer.BeginSection("Abort requested. Killing the process!").Dispose(); }; task.Terminated += delegate { writer.End(); writer.WriteLine("Exit Code: {0}", task.ExitCode); writer.End(); }; }
/// <summary> /// Creates a new process task but does not start it. /// </summary> /// <remarks> /// <para> /// The output of the process will be logged and included as part of the test results. It /// may also be examined using the <see cref="ProcessTask.ConsoleOutput" /> and /// <see cref="ProcessTask.ConsoleError" /> properties while the process executes and /// after it terminates. /// </para> /// <para> /// There is no need to call <see cref="WatchTask" /> on the returned task. /// </para> /// </remarks> /// <param name="executablePath">The path of the executable executable.</param> /// <param name="arguments">The arguments for the executable.</param> /// <param name="workingDirectory">The working directory.</param> /// <returns>The new thread task.</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="executablePath"/>, /// <paramref name="arguments"/> or <paramref name="workingDirectory"/> is null.</exception> public static ProcessTask CreateProcessTask(string executablePath, string arguments, string workingDirectory) { if (executablePath == null) throw new ArgumentNullException("executablePath"); if (arguments == null) throw new ArgumentNullException("arguments"); if (workingDirectory == null) throw new ArgumentNullException("workingDirectory"); var task = new ProcessTask(executablePath, arguments, workingDirectory); task.CaptureConsoleOutput = true; task.CaptureConsoleError = true; ConfigureProcessTaskForLogging(task, TestLog.Default); WatchTask(task); return task; }