public ProcessTrackTask(MainViewModel viewModelSource) { this.viewModelSource = viewModelSource; var tracker = new ProcessTracker(); tracker.Start(10000); tracker.ProcessStarted += this.Tracker_ProcessStarted; tracker.ProcessStoped += Tracker_ProcessStoped; }
public Task <bool> StartServer(ProcessTracker server) { throw new NotImplementedException(); }
/// <summary> /// Run a single scenario. Passing 0 for scenarioIndex runs all scenarios. /// Once the scenario is done executing, the results are copied into the /// results directory. /// /// If true is returned, then exitCode was assigned and can be checked. /// If false is returned the value of exitCode is considered undefined. /// </summary> /// <param name="scenarioIndex">The scenario to run.</param> /// <returns>false if the job was not started, true if the job started and exitcode was assigned a value.</returns> private bool RunJob(int scenarioIndex, ref int exitCode) { bool rval = false; string envOpts = string.Format("/s /r:{0} {1}", scenarioIndex, EnvxFilePath); ProcessTracker tracker = new ProcessTracker(EnvExePath, envOpts); if (tracker.Start()) { tracker.WaitForCompletion(); logger.Debug(string.Format("Envision exited. Exit code: {0}", exitCode)); rval = true; } exitCode = tracker.ExitCode; return rval; }
private async Task <(Uri url, CancellationToken hostExitToken)> StartIISExpressAsync(string contentRoot) { using (Logger.BeginScope("StartIISExpress")) { var iisExpressPath = GetIISExpressPath(); for (var attempt = 0; attempt < MaximumAttempts; attempt++) { var uri = TestUriHelper.BuildTestUri(ServerType.IISExpress, DeploymentParameters.ApplicationBaseUriHint); var port = uri.Port; if (port == 0) { port = (uri.Scheme == "https") ? TestPortHelper.GetNextSSLPort() : TestPortHelper.GetNextPort(); } Logger.LogInformation("Attempting to start IIS Express on port: {port}", port); PrepareConfig(contentRoot, port); var parameters = string.IsNullOrEmpty(DeploymentParameters.ServerConfigLocation) ? string.Format(CultureInfo.InvariantCulture, "/port:{0} /path:\"{1}\" /trace:error /systray:false", uri.Port, contentRoot) : string.Format(CultureInfo.InvariantCulture, "/site:{0} /config:{1} /trace:error /systray:false", DeploymentParameters.SiteName, DeploymentParameters.ServerConfigLocation); Logger.LogInformation("Executing command : {iisExpress} {parameters}", iisExpressPath, parameters); var startInfo = new ProcessStartInfo { FileName = iisExpressPath, Arguments = parameters, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, // VS sets current directory to C:\Program Files\IIS Express WorkingDirectory = Path.GetDirectoryName(iisExpressPath) }; AddEnvironmentVariablesToProcess(startInfo, DeploymentParameters.EnvironmentVariables); Uri url = null; var started = new TaskCompletionSource <bool>(); var process = new Process() { StartInfo = startInfo }; process.OutputDataReceived += (sender, dataArgs) => { if (string.Equals(dataArgs.Data, UnableToStartIISExpressMessage, StringComparison.Ordinal)) { // We completely failed to start and we don't really know why started.TrySetException(new InvalidOperationException("Failed to start IIS Express")); } else if (string.Equals(dataArgs.Data, FailedToInitializeBindingsMessage, StringComparison.Ordinal)) { started.TrySetResult(false); } else if (string.Equals(dataArgs.Data, IISExpressRunningMessage, StringComparison.Ordinal)) { started.TrySetResult(true); } else if (!string.IsNullOrEmpty(dataArgs.Data)) { var m = UrlDetectorRegex.Match(dataArgs.Data); if (m.Success) { url = new Uri(m.Groups["url"].Value); } } }; process.EnableRaisingEvents = true; var hostExitTokenSource = new CancellationTokenSource(); process.Exited += (sender, e) => { Logger.LogInformation("iisexpress Process {pid} shut down", process.Id); // If TrySetResult was called above, this will just silently fail to set the new state, which is what we want started.TrySetException(new Exception($"Command exited unexpectedly with exit code: {process.ExitCode}")); TriggerHostShutdown(hostExitTokenSource); }; process.StartAndCaptureOutAndErrToLogger("iisexpress", Logger); Logger.LogInformation("iisexpress Process {pid} started", process.Id); if (process.HasExited) { Logger.LogError("Host process {processName} {pid} exited with code {exitCode} or failed to start.", startInfo.FileName, process.Id, process.ExitCode); throw new Exception("Failed to start host"); } // Wait for the app to start // The timeout here is large, because we don't know how long the test could need. We cover a lot // of error cases above, but I want to make sure we eventually give up and don't hang the build // just in case we missed one -anurse if (!await started.Task.TimeoutAfter(TimeSpan.FromMinutes(15))) { Logger.LogInformation("iisexpress Process {pid} failed to bind to port {port}, trying again", process.Id, port); // Wait for the process to exit and try again process.WaitForExit(30 * 1000); await Task.Delay(1000); // Wait a second to make sure the socket is completely cleaned up } else { _hostProcess = process; // Ensure iisexpress.exe is killed if test process termination is non-graceful. // Prevents locked files when stop debugging unit test. ProcessTracker.Add(_hostProcess); // cache the process start time for verifying log file name. var _ = _hostProcess.StartTime; Logger.LogInformation("Started iisexpress successfully. Process Id : {processId}, Port: {port}", _hostProcess.Id, port); return(url : url, hostExitToken : hostExitTokenSource.Token); } } var message = $"Failed to initialize IIS Express after {MaximumAttempts} attempts to select a port"; Logger.LogError(message); throw new TimeoutException(message); } }