public Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver receiver, CancellationToken cancellationToken, int maxTimeToOutputResponse) { this.ReceivedCommands.Add(command); if (this.Commands.ContainsKey(command)) { if (receiver != null) { StringReader reader = new StringReader(this.Commands[command]); while (reader.Peek() != -1) { receiver.AddOutput(reader.ReadLine()); } receiver.Flush(); } } else { throw new ArgumentOutOfRangeException(nameof(command), $"The command '{command}' was unexpected"); } return(Task.FromResult(true)); }
public Task ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver rcvr, CancellationToken cancellationToken, int maxTimeToOutputResponse) { this.ReceivedCommands.Add(command); if (this.Commands.ContainsKey(command)) { if (rcvr != null) { StringReader reader = new StringReader(this.Commands[command]); while (reader.Peek() != -1) { rcvr.AddOutput(reader.ReadLine()); } rcvr.Flush(); } } else { throw new ArgumentOutOfRangeException(nameof(command)); } return Task.FromResult(true); }
/// <inheritdoc/> public async Task ExecuteRemoteCommandAsync(string command, DeviceData device, IShellOutputReceiver receiver, CancellationToken cancellationToken, int maxTimeToOutputResponse) { this.EnsureDevice(device); using (IAdbSocket socket = this.adbSocketFactory(this.EndPoint)) { cancellationToken.Register(() => socket.Dispose()); this.SetDevice(socket, device); socket.SendAdbRequest($"shell:{command}"); var response = socket.ReadAdbResponse(); try { using (StreamReader reader = new StreamReader(socket.GetShellStream(), Encoding)) { // Previously, we would loop while reader.Peek() >= 0. Turns out that this would // break too soon in certain cases (about every 10 loops, so it appears to be a timing // issue). Checking for reader.ReadLine() to return null appears to be much more robust // -- one of the integration test fetches output 1000 times and found no truncations. while (!cancellationToken.IsCancellationRequested) { var line = await reader.ReadLineAsync().ConfigureAwait(false); if (line == null) { break; } if (receiver != null) { receiver.AddOutput(line); } } } } catch (Exception e) { // If a cancellation was requested, this main loop is interrupted with an exception // because the socket is closed. In that case, we don't need to throw a ShellCommandUnresponsiveException. // In all other cases, something went wrong, and we want to report it to the user. if (!cancellationToken.IsCancellationRequested) { throw new ShellCommandUnresponsiveException(e); } } finally { if (receiver != null) { receiver.Flush(); } } } }
public string SendCommand(string command) { receiver.Flush(); Client.ExecuteRemoteCommand(command, deviceData, receiver); return(receiver.ToString()); }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="System.IO.FileNotFoundException"></exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand( IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse ) { Socket socket = new Socket ( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); if ( !device.IsOnline ) { return; } try { socket.Connect ( endPoint ); socket.Blocking = true; SetDevice ( socket, device ); byte[] request = FormAdbRequest ( "shell:" + command ); if ( !Write ( socket, request ) ) { throw new AdbException ( "failed submitting shell command" ); } AdbResponse resp = ReadAdbResponse ( socket, false /* readDiagString */); if ( !resp.IOSuccess || !resp.Okay ) { throw new AdbException ( "sad result from adb: " + resp.Message ); } byte[] data = new byte[16384]; int timeToResponseCount = 0; while ( true ) { int count; if ( rcvr != null && rcvr.IsCancelled ) { this.LogWarn("execute: cancelled" ); throw new OperationCanceledException ( ); } count = socket.Receive ( data ); if ( count < 0 ) { // we're at the end, we flush the output rcvr.Flush ( ); this.LogInfo("execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count ); break; } else if ( count == 0 ) { try { int wait = WAIT_TIME * 5; timeToResponseCount += wait; if ( maxTimeToOutputResponse > 0 && timeToResponseCount > maxTimeToOutputResponse ) { throw new AdbException ( ); } Thread.Sleep ( wait ); } catch ( ThreadInterruptedException ) { } } else { timeToResponseCount = 0; string[] cmd = command.Trim ( ).Split ( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ); string sdata = data.GetString ( 0, count, AdbHelper.DEFAULT_ENCODING ); var sdataTrimmed = sdata.Trim ( ); if ( sdataTrimmed.EndsWith ( String.Format ( "{0}: not found", cmd[0] ) ) ) { this.LogWarn( "The remote execution returned: '{0}: not found'", cmd[0] ); throw new FileNotFoundException ( string.Format ( "The remote execution returned: '{0}: not found'", cmd[0] ) ); } if ( sdataTrimmed.EndsWith ( "No such file or directory" ) ) { this.LogWarn ( "The remote execution returned: {0}", sdataTrimmed ); throw new FileNotFoundException ( String.Format ( "The remote execution returned: {0}", sdataTrimmed ) ); } // for "unknown options" if ( sdataTrimmed.Contains ( "Unknown option" ) ) { this.LogWarn ( "The remote execution returned: {0}", sdataTrimmed ); throw new UnknownOptionException ( sdataTrimmed ); } // for "aborting" commands if ( sdataTrimmed.IsMatch ( "Aborting.$" ) ) { this.LogWarn ( "The remote execution returned: {0}", sdataTrimmed ); throw new CommandAbortingException ( sdataTrimmed ); } // for busybox applets // cmd: applet not found if ( sdataTrimmed.IsMatch ( "applet not found$" ) && cmd.Length > 1 ) { this.LogWarn ( "The remote execution returned: '{0}'", sdataTrimmed ); throw new FileNotFoundException ( string.Format ( "The remote execution returned: '{0}'", sdataTrimmed ) ); } // checks if the permission to execute the command was denied. // workitem: 16822 if ( sdataTrimmed.IsMatch ( "(permission|access) denied$" ) ) { this.LogWarn ( "The remote execution returned: '{0}'", sdataTrimmed ); throw new PermissionDeniedException ( String.Format ( "The remote execution returned: '{0}'", sdataTrimmed ) ); } // Add the data to the receiver if ( rcvr != null ) { rcvr.AddOutput ( data, 0, count ); } } } } /*catch ( Exception e ) { Log.e ( TAG, e ); Console.Error.WriteLine ( e.ToString ( ) ); throw; }*/ finally { if ( socket != null ) { socket.Close ( ); } rcvr.Flush ( ); } }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="System.IO.FileNotFoundException"> /// </exception> /// <exception cref="Managed.Adb.Exceptions.UnknownOptionException"></exception> /// <exception cref="Managed.Adb.Exceptions.CommandAbortingException"></exception> /// <exception cref="Managed.Adb.Exceptions.PermissionDeniedException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse) { using(var socket = ExecuteRawSocketCommand(endPoint, device, "shell:{0}".With(command))) { socket.ReceiveTimeout = maxTimeToOutputResponse; socket.SendTimeout = maxTimeToOutputResponse; try { byte[] data = new byte[16384]; int count = -1; while(count != 0) { if(rcvr != null && rcvr.IsCancelled) { Log.w(TAG, "execute: cancelled"); throw new OperationCanceledException(); } count = socket.Receive(data); if(count == 0) { // we're at the end, we flush the output rcvr.Flush(); Log.w(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); } else { string[] cmd = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = data.GetString(0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim(); if(sdataTrimmed.EndsWith(String.Format("{0}: not found", cmd[0]))) { Log.w(TAG, "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if(sdataTrimmed.EndsWith("No such file or directory")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(String.Format("The remote execution returned: {0}", sdataTrimmed)); } // for "unknown options" if(sdataTrimmed.Contains("Unknown option")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new UnknownOptionException(sdataTrimmed); } // for "aborting" commands if(sdataTrimmed.IsMatch("Aborting.$")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new CommandAbortingException(sdataTrimmed); } // for busybox applets // cmd: applet not found if(sdataTrimmed.IsMatch("applet not found$") && cmd.Length > 1) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if(sdataTrimmed.IsMatch("(permission|access) denied$")) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(String.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if(rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } catch(SocketException) { throw new ShellCommandUnresponsiveException(); } finally { rcvr.Flush(); } } }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="System.IO.FileNotFoundException"></exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse) { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (!device.IsOnline) { return; } try { socket.Connect(endPoint); socket.ReceiveTimeout = maxTimeToOutputResponse; socket.SendTimeout = maxTimeToOutputResponse; socket.Blocking = true; SetDevice(socket, device); byte[] request = FormAdbRequest("shell:" + command); if (!Write(socket, request)) { throw new AdbException("failed submitting shell command"); } AdbResponse resp = ReadAdbResponse(socket, false /* readDiagString */); if (!resp.IOSuccess || !resp.Okay) { throw new AdbException("sad result from adb: " + resp.Message); } byte[] data = new byte[16384]; int count = -1; while (count != 0) { if (rcvr != null && rcvr.IsCancelled) { Log.w(TAG, "execute: cancelled"); throw new OperationCanceledException( ); } count = socket.Receive(data); if (count == 0) { // we're at the end, we flush the output rcvr.Flush( ); Log.w(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); } else { string[] cmd = command.Trim( ).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = data.GetString(0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim( ); if (sdataTrimmed.EndsWith(String.Format("{0}: not found", cmd[0]))) { Log.w(TAG, "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if (sdataTrimmed.EndsWith("No such file or directory")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(String.Format("The remote execution returned: {0}", sdataTrimmed)); } // for "unknown options" if (sdataTrimmed.Contains("Unknown option")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new UnknownOptionException(sdataTrimmed); } // for "aborting" commands if (sdataTrimmed.IsMatch("Aborting.$")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new CommandAbortingException(sdataTrimmed); } // for busybox applets // cmd: applet not found if (sdataTrimmed.IsMatch("applet not found$") && cmd.Length > 1) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if (sdataTrimmed.IsMatch("(permission|access) denied$")) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(String.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if (rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } catch (SocketException s) { throw new ShellCommandUnresponsiveException( ); } finally { if (socket != null) { socket.Close( ); } rcvr.Flush( ); } }
/// <inheritdoc/> public void ExecuteRemoteCommand(string command, DeviceData device, IShellOutputReceiver receiver, CancellationToken cancellationToken, int maxTimeToOutputResponse) { this.EnsureDevice(device); using (IAdbSocket socket = Factories.AdbSocketFactory(this.EndPoint)) { cancellationToken.Register(() => socket.Close()); this.SetDevice(socket, device); socket.SendAdbRequest($"shell:{command}"); var response = socket.ReadAdbResponse(); try { using (StreamReader reader = new StreamReader(socket.GetShellStream(), Encoding)) { // Previously, we would loop while reader.Peek() >= 0. Turns out that this would // break too soon in certain cases (about every 10 loops, so it appears to be a timing // issue). Checking for reader.ReadLine() to return null appears to be much more robust // -- one of the integration test fetches output 1000 times and found no truncations. while (!cancellationToken.IsCancellationRequested) { var line = reader.ReadLine(); if (line == null) { break; } if (receiver != null) { receiver.AddOutput(line); } } } } catch (Exception e) { // If a cancellation was requested, this main loop is interrupted with an exception // because the socket is closed. In that case, we don't need to throw a ShellCommandUnresponsiveException. // In all other cases, something went wrong, and we want to report it to the user. if (!cancellationToken.IsCancellationRequested) { throw new ShellCommandUnresponsiveException(e); } } finally { if (receiver != null) { receiver.Flush(); } } } }
/// <summary> /// Executes the remote command. /// </summary> /// <param name="endPoint">The end point.</param> /// <param name="command">The command.</param> /// <param name="device">The device.</param> /// <param name="rcvr">The RCVR.</param> /// <param name="maxTimeToOutputResponse">The max time to output response.</param> /// <exception cref="System.OperationCanceledException"></exception> /// <exception cref="System.IO.FileNotFoundException"> /// </exception> /// <exception cref="Managed.Adb.Exceptions.UnknownOptionException"></exception> /// <exception cref="Managed.Adb.Exceptions.CommandAbortingException"></exception> /// <exception cref="Managed.Adb.Exceptions.PermissionDeniedException"></exception> /// <exception cref="Managed.Adb.Exceptions.ShellCommandUnresponsiveException"></exception> /// <exception cref="AdbException">failed submitting shell command</exception> /// <exception cref="UnknownOptionException"></exception> /// <exception cref="CommandAbortingException"></exception> /// <exception cref="PermissionDeniedException"></exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, String command, Device device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse) { using (var socket = ExecuteRawSocketCommand(endPoint, device, "shell:{0}".With(command))) { socket.ReceiveTimeout = maxTimeToOutputResponse; socket.SendTimeout = maxTimeToOutputResponse; try { byte[] data = new byte[16384]; int count = -1; while (count != 0) { if (rcvr != null && rcvr.IsCancelled) { Log.w(TAG, "execute: cancelled"); throw new OperationCanceledException(); } count = socket.Receive(data); if (count == 0) { // we're at the end, we flush the output rcvr.Flush(); Log.w(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); } else { string[] cmd = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = data.GetString(0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim(); if (sdataTrimmed.EndsWith(String.Format("{0}: not found", cmd[0]))) { Log.w(TAG, "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if (sdataTrimmed.EndsWith("No such file or directory")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(String.Format("The remote execution returned: {0}", sdataTrimmed)); } // for "unknown options" if (sdataTrimmed.Contains("Unknown option")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new UnknownOptionException(sdataTrimmed); } // for "aborting" commands if (sdataTrimmed.IsMatch("Aborting.$")) { Log.w(TAG, "The remote execution returned: {0}", sdataTrimmed); throw new CommandAbortingException(sdataTrimmed); } // for busybox applets // cmd: applet not found if (sdataTrimmed.IsMatch("applet not found$") && cmd.Length > 1) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if (sdataTrimmed.IsMatch("(permission|access) denied$")) { Log.w(TAG, "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(String.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if (rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } catch (SocketException) { throw new ShellCommandUnresponsiveException(); } finally { rcvr.Flush(); } } }
/// <summary> /// Executes a shell command on the remote device /// </summary> /// <param name="endPoint">The socket end point</param> /// <param name="command">The command to execute</param> /// <param name="device">The device to execute on</param> /// <param name="rcvr">The shell output receiver</param> /// <exception cref="FileNotFoundException">Throws if the result is 'command': not found</exception> /// <exception cref="IOException">Throws if there is a problem reading / writing to the socket</exception> /// <exception cref="OperationCanceledException">Throws if the execution was canceled</exception> /// <exception cref="EndOfStreamException">Throws if the Socket.Receice ever returns -1</exception> public void ExecuteRemoteCommand(IPEndPoint endPoint, string command, Device device, IShellOutputReceiver rcvr) { Log.I(TAG, "executing '" + command + "' on '" + device + "'."); Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (!device.IsOnline) { return; } try { socket.ReceiveTimeout = SOCKET_TIMEOUT; socket.SendTimeout = SOCKET_TIMEOUT; socket.Connect(endPoint); socket.Blocking = true; SetDevice(socket, device); byte[] request = FormAdbRequest("shell:" + command); if (!Write(socket, request)) { throw new AdbException("failed submitting shell command"); } AdbResponse resp = ReadAdbResponse(socket, false /* readDiagstring */); if (!resp.IOSuccess || !resp.Okay) { throw new AdbException("sad result from adb: " + resp.Message); } byte[] data = new byte[16384]; int count = -1; socket.ReceiveTimeout = SOCKET_TIMEOUT_SHELLCOMMAND; while (count != 0) { if (rcvr != null && rcvr.IsCancelled) { Log.W(TAG, "execute: cancelled"); throw new OperationCanceledException(); } count = socket.Receive(data); if (count < 0) { // we're at the end, we flush the output rcvr.Flush(); Log.W(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count); throw new EndOfStreamException(); } else if (count == 0) { // do nothing } else { string[] cmd = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string sdata = StringHelper.GetString(data, 0, count, AdbHelper.DEFAULT_ENCODING); var sdataTrimmed = sdata.Trim(); if (sdataTrimmed.EndsWith(string.Format("{0}: not found", cmd[0]))) { Log.W("AdbHelper", "The remote execution returned: '{0}: not found'", cmd[0]); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0])); } if (sdataTrimmed.EndsWith("No such file or directory")) { Log.W("AdbHelper", "The remote execution returned: {0}", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: {0}", sdataTrimmed)); } // for busybox applets // cmd: applet not found if (cmd.Length > 1 && sdataTrimmed.EndsWith(string.Format("{0}: applet not found", cmd[1]))) { Log.W("AdbHelper", "The remote execution returned: '{0}'", sdataTrimmed); throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // checks if the permission to execute the command was denied. // workitem: 16822 if (sdataTrimmed.EndsWith(string.Format("{0}: permission denied", cmd[0])) || sdataTrimmed.EndsWith(string.Format("{0}: access denied", cmd[0]))) { Log.W("AdbHelper", "The remote execution returned: '{0}'", sdataTrimmed); throw new PermissionDeniedException(string.Format("The remote execution returned: '{0}'", sdataTrimmed)); } // Add the data to the receiver if (rcvr != null) { rcvr.AddOutput(data, 0, count); } } } } /*catch ( Exception e ) { * Log.e ( "AdbHelper", e ); * throw; * }*/ finally { if (socket != null) { socket.Close(); } rcvr.Flush(); } }