Class CommandRequest

java.lang.Object
org.metricshub.winrm.CommandRequest

public final class CommandRequest extends Object
A command being prepared for execution, created by WinRMClient.command(String). Every option has a sensible default; execute() runs the command and returns its output and exit code, start() returns a RemoteProcess whose output can be consumed while the command is still running.
  • Method Details

    • workingDirectory

      public CommandRequest workingDirectory(String workingDirectory)
      Set the working directory of the remote process. The remote command shell is created on the first command a client executes and is reused afterward, so this setting takes effect only when this is the client's first command.
      Parameters:
      workingDirectory - the working directory path on the remote host
      Returns:
      this request
    • timeout

      public CommandRequest timeout(Duration timeout)
      Set the timeout of this command. For execute() it is a wall-clock deadline covering file uploads and the command itself; for start() it is an inactivity timeout — the longest silence tolerated from the server between two responses, with no overall deadline. Default: the client's timeout.
      Parameters:
      timeout - the timeout (at least one millisecond)
      Returns:
      this request
    • charset

      public CommandRequest charset(Charset charset)
      Set the charset used to decode the command output. Default: WindowsRemoteExecutor.SHELL_OUTPUT_CHARSET (UTF-8), which is what the remote shell emits — its console code page is set to 65001 when the shell is created, whatever the remote locale. Override this only for a command that changes the console code page itself (a leading chcp) or writes raw bytes in another encoding to its standard output.
      Parameters:
      charset - the output charset
      Returns:
      this request
    • stdinCharset

      public CommandRequest stdinCharset(Charset charset)
      Set the charset used to encode the command's standard input, when it differs from the output charset. Default: the output charset (see charset(Charset)).

      The two directions are not symmetric on Windows. Output follows the shell's console code page, which this client pins to UTF-8. Input written to a command created with console-mode stdin is converted by the WinRM service with the remote machine's ANSI code page instead — so an interactive session (the CLI's shell subcommand) must encode what it sends with that code page, whatever the console code page is. Input handed to a command created with pipe semantics (any stdin(...) on this request) reaches the process unconverted and needs no override.

      Parameters:
      charset - the input charset
      Returns:
      this request
    • upload

      public CommandRequest upload(Path... files)
      Copy local files to the remote host (through the WinRM connection itself) before running the command. Each reference to a local file path inside the command line is rewritten to the remote copy, exactly like the legacy WinRMCommandExecutor:
      
       client.command("CSCRIPT c:\\scripts\\collect.vbs")
       	.upload(Path.of("c:\\scripts\\collect.vbs"))
       	.execute();
       
      transfers the script and executes CSCRIPT <remote copy>.
      Parameters:
      files - the local files to copy
      Returns:
      this request
    • stdin

      public CommandRequest stdin(String text)
      Feed the given text to the command's standard input. The text is encoded with the same charset used to decode the output (see charset(Charset)) and delivered in full — split into protocol-sized chunks when large — right after the command starts, ending with the end-of-input mark so the remote stdin reaches EOF.

      Supplying input switches the remote stdin to pipe semantics (WINRS_CONSOLEMODE_STDIN=FALSE): tools like sort or findstr consume it and terminate on EOF, exactly as with a local < redirection.

      
       CommandResult result = client.command("sort").stdin("beta\nalpha\n").execute();
       
      Works with both execute() and start(); with start(), the RemoteProcess.stdin() writer is closed from the start — pre-supplied and interactive input are mutually exclusive. The input is delivered before any output is read: feeding a large input to a command that floods its output in the meantime can deadlock both sides, exactly like the Process pipes — the caller's to avoid.
      Parameters:
      text - the input text
      Returns:
      this request
    • stdin

      public CommandRequest stdin()
      Declare that the command will be fed standard input interactively, through RemoteProcess.stdin(), without pre-supplying it: the remote stdin switches to pipe semantics (WINRS_CONSOLEMODE_STDIN=FALSE), so closing the writer actually delivers EOF — a console-mode stdin never reaches EOF for tools like sort or findstr.
      
       try (RemoteProcess p = client.command("sort").stdin().start()) {
       	try (BufferedWriter in = p.stdin()) {
       		in.write("beta\nalpha\n");
       	} // EOF: sort now sorts and exits
       	p.waitFor();
       }
       
      Only meaningful with start()execute() cannot take interactive input and rejects a request configured this way. Without any stdin call, the historical console semantics are kept (what a command that never reads input, and the interactive CLI shell, want). Like every stdin variant, the LAST call wins: any previously pre-supplied input is discarded.
      Returns:
      this request
    • stdin

      public CommandRequest stdin(Path file)
      Feed the content of the given local file to the command's standard input — the equivalent of a local < file redirection. Same contract as stdin(String), except the bytes are sent exactly as stored (no re-encoding).
      Parameters:
      file - the local file to read
      Returns:
      this request
    • stdin

      public CommandRequest stdin(InputStream stream)
      Feed the given stream to the command's standard input, reading it to its end. Same contract as stdin(String), except the bytes are sent exactly as read (no re-encoding). The stream is consumed when the command starts and closed afterward; it is read on the thread driving the execution, so a stream that blocks forever stalls the command.
      Parameters:
      stream - the input stream to consume
      Returns:
      this request
    • onStdout

      public CommandRequest onStdout(Consumer<String> consumer)
      Register a callback receiving each chunk of standard output as it arrives, while execute() is still running — a middle ground between collecting everything and managing a RemoteProcess: tail the output live, but keep the blocking terminal and its complete CommandResult.
      
       client.command("longRunningThing.exe")
       	.onStdout(chunk -> log.info(chunk))
       	.onStderr(chunk -> log.warn(chunk))
       	.execute();
       
      The callback is invoked on an internal worker thread (never concurrently), with output decoded incrementally: a chunk is a run of characters as the server delivered them, not necessarily whole lines.
      Parameters:
      consumer - the standard output consumer
      Returns:
      this request
    • onStderr

      public CommandRequest onStderr(Consumer<String> consumer)
      Register a callback receiving each chunk of standard error as it arrives, while execute() is still running. Same contract as onStdout(Consumer).
      Parameters:
      consumer - the standard error consumer
      Returns:
      this request
    • execute

      public CommandResult execute()
      Execute the command and collect its complete output. When onStdout(Consumer) or onStderr(Consumer) callbacks are registered, they additionally receive the output chunk by chunk while the command runs; the returned result is complete either way.
      Returns:
      the command result: stdout, stderr, exit code, and execution time
      Throws:
      WinRMTimeoutException - when the timeout elapses first
      WinRMAuthenticationException - when the credentials are rejected
      WinRMFaultException - when the remote service answers with a WSMan fault
      WinRMClientException - for any other failure
    • start

      public RemoteProcess start()
      Start the command and return a RemoteProcess handle over it — the streaming counterpart of execute(): stdout and stderr can be consumed while the command is still running, and the handle exposes the eventual exit code.
      
       try (RemoteProcess process = client.command("wevtutil qe System /f:text").start()) {
       	try (BufferedReader out = process.stdout()) {
       		out.lines().forEach(this::process);
       	}
       	int exitCode = process.waitFor();
       }
       

      The process must be closed — use try-with-resources. It holds the client's serial connection until the command completes or the handle is closed; closing early terminates the remote command (WinRM terminate Signal). The timeout acts as an inactivity timeout — see RemoteProcess. File uploads run here, before the command starts.

      Returns:
      the running process handle, to use with try-with-resources
      Throws:
      WinRMTimeoutException - when the command startup times out
      WinRMAuthenticationException - when the credentials are rejected
      WinRMFaultException - when the remote service answers with a WSMan fault
      WinRMClientException - for any other failure