/// <summary> /// Runs <code>adb (command)</code> and returns the result. /// AdbException is thrown if the return code is non-zero, unless the return code is in allowedExitCodes. /// </summary> /// <param name="command">The command to execute, without the <code>adb</code> executable name</param> /// <returns>The process output from executing the file</returns> public async Task <ProcessOutput> RunCommand(string command, params int[] allowedExitCodes) { if (_adbPath == null) { await PrepareAdbPath(); } Debug.Assert(_adbPath != null); _logger.Debug($"Executing ADB command: adb {command}"); while (true) { ProcessOutput output = await ProcessUtil.InvokeAndCaptureOutput(_adbPath, command); _logger.Verbose($"Standard output: \"{output.StandardOutput}\""); if (output.ErrorOutput.Length > 0) { _logger.Verbose($"Error output: \"{output.ErrorOutput}\""); } _logger.Verbose($"Exit code: {output.ExitCode}"); // Command execution was a success if the exit code was zero or an allowed exit code // -1073740940 is always allowed as some ADB installations return it randomly, even when commands are successful. if (output.ExitCode == 0 || allowedExitCodes.Contains(output.ExitCode) || output.ExitCode == -1073740940) { return(output); } string allOutput = output.StandardOutput + output.ErrorOutput; // We repeatedly prompt the user to plug in their quest if it is not plugged in, or the device is offline, or if there are multiple devices if (allOutput.Contains("no devices/emulators found")) { await _onDisconnect(DisconnectionType.NoDevice); } else if (allOutput.Contains("device offline")) { await _onDisconnect(DisconnectionType.DeviceOffline); } else if (allOutput.Contains("multiple devices") || output.ErrorOutput.Contains("more than one device/emulator")) { await _onDisconnect(DisconnectionType.MultipleDevices); } else if (allOutput.Contains("unauthorized")) { await _onDisconnect(DisconnectionType.Unauthorized); } else { // Throw an exception as ADB gave a non-zero exit code so the command must've failed throw new AdbException(allOutput); } } }
/// <summary> /// Checks if ADB is on PATH, and downloads it if not /// </summary> public async Task PrepareAdbPath() { try { await ProcessUtil.InvokeAndCaptureOutput(_adbExecutableName, "-version"); // If the ADB EXE is already on PATH, we can just use that _adbPath = _adbExecutableName; _logger.Information("Located ADB install on PATH"); } catch (Win32Exception) // Thrown if the file we attempted to execute does not exist (on mac & linux as well, despite saying Win32) { // Otherwise, we download the tool and make it executable (only necessary on mac & linux) _adbPath = await _filesDownloader.GetFileLocation(ExternalFileType.PlatformTools); // Download ADB if it hasn't been already } }
private Task <ProcessOutput> InvokeJava(string args) { return(ProcessUtil.InvokeAndCaptureOutput(_javaExecutableName, args)); }