Search code examples
jsch

Running any exe with Jsch in a AWS windows server not working


We have a Windows server in AWS and we are interacting using Jsch. We are able to write a file there. We can also execute this command: tasklist | findstr myprogram to check if myprogram is running and correctly see the resulting output of executing that command when myprogram is running or not.

The thing is that, when myprogram is not running, we want to launch it. And for some reason there is no way to launch any .exe remotely. I suspect we are missing something. Like in the other cases, we use an exec channel. We get neither output nor error, nothing. Am I missing something? There is something special with the .exe to be taken into account? Maybe the way we write the path? Maybe the way we launch the command?

 cmd = "start cmd /k C:\\path\\to\\myprogram.exe";

Same thing happens with different exes, so is not a thing of myprogram. Following the method used to execute the commands. The output is printed for a command like taskklist, also if you execute a command with an error, the error is correctly printed.

    private List<String> executeSSHCommand(String cmd, Session session) {
    try {
        channel = (ChannelExec) session.openChannel("exec");

        ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
        ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();

        InputStream in = channel.getInputStream();
        InputStream err = channel.getExtInputStream();
        channel.setCommand(cmd);
        channel.connect();

        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0) break;
                outputBuffer.write(tmp, 0, i);
            }
            while (err.available() > 0) {
                int i = err.read(tmp, 0, 1024);
                if (i < 0) break;
                errorBuffer.write(tmp, 0, i);
            }
            if (channel.isClosed()) {
                if ((in.available() > 0) || (err.available() > 0)) continue;
                System.out.println("exit-status: " + channel.getExitStatus());
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ee) {
            }
        }

        String output = outputBuffer.toString("UTF-8");
        String errs = errorBuffer.toString();
        System.out.println("Executing " + cmd + ": ");
        System.out.println(" - output: " + output);
        System.out.println(" - error: " + errs);
        List<String> out = new ArrayList<>();
        out.add(output);
        out.add(errs);
        return out;
    } catch (JSchException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Solution

  • After unsuccessfully trying several combinations of start, cmd, /k, /c,... I could only make it work like this. The command is just the executable:

    cmd = "C:\\path\\to\\myprogram.exe";
    

    And now the method does not read the output or the error:

        private List<String> executeSSHCommandDoNoReadOutput(String cmd, Session session) {
        try {
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(cmd);
            channel.connect();
    
        } catch (JSchException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        channel.disconnect();
        return null;
    }
    

    Not specially happy with the workaround but is the only way I could make it work. I don't get why all the other things were not working.