/// <summary> /// Attempts to start the process and returns a task that is completed when the process /// exits with an exit code of zero (success). Standard output and error output are /// captured. /// </summary> /// <returns>A task evaluates to the output of the process.</returns> /// <exception cref="ProcessException"> /// Thrown if the process cannot be started, or if it does not exit within the timeout /// period that was specified when the process was created. /// </exception> /// <exception cref="ProcessExecutionException"> /// Thrown if the process exits with a non-zero exit code. Use the OutputLines and /// ErrorLines properties to get the process output and error text, respectively. /// </exception> public static async Task <List <string> > RunToExitWithSuccessCapturingOutputAsync( this IProcess process) { List <string> outputLines = new List <string>(); List <string> errorLines = new List <string>(); process.OutputDataReceived += (obj, args) => { if (args.Text != null) { outputLines.Add(args.Text); } }; process.ErrorDataReceived += (obj, args) => { if (args.Text != null) { errorLines.Add(args.Text); } }; var code = await process.RunToExitAsync(); if (code != 0) { throw new ProcessExecutionException( ErrorStrings.ProcessExitedWithErrorCode(process.ProcessName, code), code, outputLines, errorLines); } return(outputLines); }
/// <summary> /// Checks exit code of the process. If it is non-zero it throws /// the ProcessExecutionException. /// </summary> /// <exception cref="ProcessExecutionException"> /// Thrown if the process exits with a non-zero exit code. /// </exception> /// <param name="code">Exit code of the process.</param> public static void CheckExitCode(this IProcess process, int code) { if (code != 0) { throw new ProcessExecutionException( ErrorStrings.ProcessExitedWithErrorCode(process.ProcessName, code), code); } }
/// <summary> /// Parses an elf binary or symbol file and returns the build ID encoded /// in the .note.gnu.build-id section of the file. /// </summary> /// <param name="filepath">The local or remote absolute file path.</param> /// <param name="target">Optional parameter specifying the remote gamelet.</param> /// <returns>A non-empty build id.</returns> /// <exception cref="BinaryFileUtilException"> /// Thrown when an error is encountered reading or parsing the build id. /// InnerException contains more details. /// </exception> public async Task <BuildId> ReadBuildIdAsync(string filepath, SshTarget target = null) { try { var outputLines = await ReadSectionFromFileAsync(".note.gnu.build-id", filepath, target); var hexString = ParseHexDump(outputLines); var result = ParseBuildIdOutput(hexString); if (result == BuildId.Empty) { throw new InvalidBuildIdException( ErrorStrings.FailedToReadBuildId(filepath, ErrorStrings.EmptyBuildId)); } return(result); } catch (ProcessExecutionException e) { LogObjdumpOutput(e); // objdump returned an error code, possibly because the file being parsed is not // actually an elf file. With an SSH target, exit code 255 means SSH failed before // it had a chance to execute the remote command. if (target != null && e.ExitCode < 255) { // The remote command failed, so we need to fix the exception message. // TODO: ManagedProcess should report the remote filename. throw new BinaryFileUtilException( ErrorStrings.FailedToReadBuildId( filepath, ErrorStrings.ProcessExitedWithErrorCode( YetiConstants.ObjDumpLinuxExecutable, e.ExitCode)), e); } else { throw new BinaryFileUtilException( ErrorStrings.FailedToReadBuildId(filepath, e.Message), e); } } catch (ProcessException e) { // objdump failed to launch, possibly because the SDK was not found. With an SSH // target, this indicates that SSH failed to launch. In either case, the specific // filepath was never accessed, so it is not part of the error. throw new BinaryFileUtilException( ErrorStrings.FailedToReadBuildId(e.Message), e); } catch (FormatException e) { // Indicates the build ID section is malformed. throw new InvalidBuildIdException( ErrorStrings.FailedToReadBuildId( filepath, ErrorStrings.MalformedBuildID), e); } }