Exemplo n.º 1
0
        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));
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        /// <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();
                    }
                }
            }
        }
Exemplo n.º 4
0
 public string SendCommand(string command)
 {
     receiver.Flush();
     Client.ExecuteRemoteCommand(command, deviceData, receiver);
     return(receiver.ToString());
 }
Exemplo n.º 5
0
        /// <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 ( );
            }
        }
Exemplo n.º 6
0
        /// <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();
                }
            }
        }
Exemplo n.º 7
0
        /// <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( );
            }
        }
Exemplo n.º 8
0
        /// <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();
                    }
                }
            }
        }
Exemplo n.º 9
0
        /// <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();
                }
            }
        }
Exemplo n.º 10
0
        /// <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();
            }
        }