Class WinRMClient
- All Implemented Interfaces:
AutoCloseable
try (
WinRMClient client = WinRMClient.builder("server01.acme.com")
.credentials("ACME\\admin", password)
.timeout(Duration.ofSeconds(30))
.build()) {
WqlResult services = client.wql("SELECT Name, State FROM Win32_Service").execute();
for (WqlRow row : services) {
System.out.println(row.string("Name") + " is " + row.string("State"));
}
CommandResult result = client.command("ipconfig /all").execute();
System.out.println(result.stdout());
}
Besides the blocking execute() terminals, both operations can stream:
WqlRequest.stream() yields WQL rows lazily page by page, and
CommandRequest.start() returns a RemoteProcess whose output is consumed while
the command is still running.
Thread-safety: a client may be shared between threads, but a WinRM connection is a serial channel — concurrent operations are executed one at a time, and an open stream or process holds the connection until it is closed.
Failures are reported through the unchecked
WinRMClientException hierarchy; the legacy static
helpers (WinRMWqlExecutor,
WinRMCommandExecutor) and their checked exceptions are
unaffected.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classBuilder ofWinRMClientinstances: connection-scoped settings with sensible defaults. -
Method Summary
Modifier and TypeMethodDescriptionstatic WinRMClient.BuilderStart building a client for the given host.voidclose()Close the client and release its connection.Prepare a command execution.hostname()Get the hostname this client connects to.powerShell(String script) Prepare a PowerShell script execution.voiduploadFile(Path localFile, String remoteFile) Copy a local file to an explicit path on the remote host, through the WinRM connection itself (no SMB, no extra port).Prepare a WQL query.
-
Method Details
-
builder
Start building a client for the given host.- Parameters:
hostname- the host to connect to (mandatory; for Kerberos, use the FQDN the KDC knows)- Returns:
- a new
WinRMClient.Builder
-
wql
Prepare a WQL query. Nothing is sent untilWqlRequest.execute()is called.- Parameters:
query- the WQL query, e.g.SELECT Name, State FROM Win32_Service- Returns:
- the request, to configure and execute
-
command
Prepare a command execution. Nothing is sent untilCommandRequest.execute()is called.- Parameters:
commandLine- the command line to execute (run throughcmd.exeby the remote shell)- Returns:
- the request, to configure and execute
-
powerShell
Prepare a PowerShell script execution. Nothing is sent untilCommandRequest.execute()is called.The script travels base64-encoded (
powershell.exe -NoProfile -NonInteractive -EncodedCommand ...), so it needs no quoting or escaping whatsoever: quotes, pipes, newlines, and$variablesreach PowerShell exactly as written.
The returned request is the same as forCommandResult result = client.powerShell( "Get-Service | Where-Object { $_.Status -eq 'Running' } | Select-Object -First 5 Name" ).execute();command(String): every option and both terminals apply unchanged — includingCommandRequest.upload(Path...), whose path rewriting happens on the script text before it is encoded, so a script referencing an uploaded file runs against the remote copy.powershell.exeexits with 0 on success and 1 when the script ends with a terminating error; callexit <n>in the script for a specific exit code.There is no practical script size limit. A script whose encoded invocation would not fit the remote shell's command line (roughly 3000 characters of script) is automatically transferred as a temporary
.ps1file — through the WinRM connection itself, exactly likeCommandRequest.upload(Path...)— and its content run as a dot-sourced script block, which keeps the script behaving like the encoded form: pathless ($PSScriptRootand$MyInvocation.MyCommand.Pathstay empty either way), top-level scope andparam(...)intact, and out of reach of the host's execution policy (which only governs script files). Only$MyInvocation's own metadata (InvocationName,Line) reflects the wrapper invocation for a transferred script. The remote copy is content-addressed, so re-running an identical script skips the transfer. Like any request with uploads, the transfer commands are then what creates the remote shell, so the shell-scopedCommandRequest.workingDirectory(String)does not apply.- Parameters:
script- the PowerShell script to execute, verbatim- Returns:
- the request, to configure and execute
- Throws:
IllegalArgumentException- when the script is blank
-
uploadFile
Copy a local file to an explicit path on the remote host, through the WinRM connection itself (no SMB, no extra port). The transfer is digest-verified and skipped when the destination already has identical content; the destination directory is created when needed. The client's timeout applies.- Parameters:
localFile- the local file to copyremoteFile- the absolute destination path on the remote host, e.g.C:\Windows\Temp\collect.ps1- Throws:
WinRMTimeoutException- when the timeout elapses firstWinRMClientException- for any other failure
-
hostname
Get the hostname this client connects to.- Returns:
- the hostname
-
close
public void close()Close the client and release its connection. Idempotent; operations attempted after closing throwIllegalStateException.- Specified by:
closein interfaceAutoCloseable
-