public static T LoadObject <T>(string path) { string json = File.ReadAllText(path, Encoding.UTF8); return(StringUtil.ConvertFromJson <T>(json)); }
public ProcessExitCodeException(int exitCode, string fileName, string arguments) : base(StringUtil.Loc("ProcessExitCode", exitCode, fileName, arguments)) { ExitCode = exitCode; }
public static void SaveObject(object obj, string path) { File.WriteAllText(path, StringUtil.ConvertToJson(obj), Encoding.UTF8); }
public async Task <int> ExecuteAsync( string workingDirectory, string fileName, string arguments, IDictionary <string, string> environment, bool requireExitCodeZero, Encoding outputEncoding, bool killProcessOnCancel, IList <string> contentsToStandardIn, bool inheritConsoleHandler, CancellationToken cancellationToken) { ArgUtil.Null(_proc, nameof(_proc)); ArgUtil.NotNullOrEmpty(fileName, nameof(fileName)); Trace.Info("Starting process:"); Trace.Info($" File name: '{fileName}'"); Trace.Info($" Arguments: '{arguments}'"); Trace.Info($" Working directory: '{workingDirectory}'"); Trace.Info($" Require exit code zero: '{requireExitCodeZero}'"); Trace.Info($" Encoding web name: {outputEncoding?.WebName} ; code page: '{outputEncoding?.CodePage}'"); Trace.Info($" Force kill process on cancellation: '{killProcessOnCancel}'"); Trace.Info($" Lines to send through STDIN: '{contentsToStandardIn?.Count ?? 0}'"); Trace.Info($" Persist current code page: '{inheritConsoleHandler}'"); _proc = new Process(); _proc.StartInfo.FileName = fileName; _proc.StartInfo.Arguments = arguments; _proc.StartInfo.WorkingDirectory = workingDirectory; _proc.StartInfo.UseShellExecute = false; _proc.StartInfo.CreateNoWindow = !inheritConsoleHandler; _proc.StartInfo.RedirectStandardInput = true; _proc.StartInfo.RedirectStandardError = true; _proc.StartInfo.RedirectStandardOutput = true; // Ensure we process STDERR even the process exit event happen before we start read STDERR stream. if (_proc.StartInfo.RedirectStandardError) { Interlocked.Increment(ref _asyncStreamReaderCount); } // Ensure we process STDOUT even the process exit event happen before we start read STDOUT stream. if (_proc.StartInfo.RedirectStandardOutput) { Interlocked.Increment(ref _asyncStreamReaderCount); } #if OS_WINDOWS // If StandardErrorEncoding or StandardOutputEncoding is not specified the on the // ProcessStartInfo object, then .NET PInvokes to resolve the default console output // code page: // [DllImport("api-ms-win-core-console-l1-1-0.dll", SetLastError = true)] // public extern static uint GetConsoleOutputCP(); StringUtil.EnsureRegisterEncodings(); #endif if (outputEncoding != null) { _proc.StartInfo.StandardErrorEncoding = outputEncoding; _proc.StartInfo.StandardOutputEncoding = outputEncoding; } // Copy the environment variables. if (environment != null && environment.Count > 0) { foreach (KeyValuePair <string, string> kvp in environment) { _proc.StartInfo.Environment[kvp.Key] = kvp.Value; } } // Set the TF_BUILD env variable. _proc.StartInfo.Environment["TF_BUILD"] = "True"; // Hook up the events. _proc.EnableRaisingEvents = true; _proc.Exited += ProcessExitedHandler; // Start the process. _stopWatch = Stopwatch.StartNew(); _proc.Start(); // Start the standard error notifications, if appropriate. if (_proc.StartInfo.RedirectStandardError) { StartReadStream(_proc.StandardError, _errorData); } // Start the standard output notifications, if appropriate. if (_proc.StartInfo.RedirectStandardOutput) { StartReadStream(_proc.StandardOutput, _outputData); } if (_proc.StartInfo.RedirectStandardInput) { // Write contents to STDIN if (contentsToStandardIn?.Count > 0) { foreach (var content in contentsToStandardIn) { // Write the contents as UTF8 to handle all characters. var utf8Writer = new StreamWriter(_proc.StandardInput.BaseStream, new UTF8Encoding(false)); utf8Writer.WriteLine(content); utf8Writer.Flush(); } } // Close the input stream. This is done to prevent commands from blocking the build waiting for input from the user. _proc.StandardInput.Close(); } using (var registration = cancellationToken.Register(async() => await CancelAndKillProcessTree(killProcessOnCancel))) { Trace.Info($"Process started with process id {_proc.Id}, waiting for process exit."); while (true) { Task outputSignal = _outputProcessEvent.WaitAsync(); var signaled = await Task.WhenAny(outputSignal, _processExitedCompletionSource.Task); if (signaled == outputSignal) { ProcessOutput(); } else { _stopWatch.Stop(); break; } } // Just in case there was some pending output when the process shut down go ahead and check the // data buffers one last time before returning ProcessOutput(); Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}."); } cancellationToken.ThrowIfCancellationRequested(); // Wait for process to finish. if (_proc.ExitCode != 0 && requireExitCodeZero) { throw new ProcessExitCodeException(exitCode: _proc.ExitCode, fileName: fileName, arguments: arguments); } return(_proc.ExitCode); }