WinRM Java Client

Overview

The WinRM Java Client is a small library that talks to the Windows Remote Management (WS-Management) service on a remote Windows host. It lets a Java application:

  • run WQL / WMI queries such as SELECT Name, State FROM Win32_Service and read the rows back (WQL Queries[1]),
  • execute remote commands — cmd.exe command lines or PowerShell scripts — capturing standard output, standard error and the exit code, optionally copying local script files to the host first (Remote Commands[2]), and
  • access remote files — read a file (whole, a byte range, a tail), download it to a local file, get its properties, or list a directory with filters evaluated on the host (Remote Files[3]).

All of them can also stream: WQL rows are consumed page by page as they arrive (stream()), command output is consumed while the command is still running (start(), returning a java.lang.Process-like handle), and file contents and directory listings are decoded as the host sends them — memory stays bounded regardless of the result size.

The standalone jar is also a command-line client[4] for the same operations (wql, command, shell, ls, stat, cat, get).

It supports NTLM over HTTP (with message encryption) and HTTPS, Kerberos (SPNEGO) over HTTPS, and HTTP Basic over HTTPS (Authentication[5]).

Since 2.0.00 the client has zero runtime dependencies (no Apache CXF / JAX-WS / JAXB stack, no SMB stack) and is immune by construction to JAXP ServiceLoader conflicts, because it uses the JDK-default XML factories. Problems are reported through exceptions only — the library pulls in no logging framework.

Warning

Upgrading from 1.x? Version 2.0.00 removed the legacy Apache CXF backend and now validates TLS certificates and verifies hostnames by default. If you connect over HTTPS to hosts with self-signed certificates, read Migrating from 1.x[6] first.

Add the dependency

The library is published on Maven Central[7].

Maven

Maven

<dependency>
  <groupId>org.metricshub</groupId>
  <artifactId>winrm-java</artifactId>
  <version>3.1.04</version>
</dependency>
Gradle (Groovy)

Gradle (Groovy)

implementation 'org.metricshub:winrm-java:3.1.04'
Gradle (Kotlin)

Gradle (Kotlin)

implementation("org.metricshub:winrm-java:3.1.04")

See Installation[8] for the coordinates, the supported JDKs, and the standalone command-line jar.

Quick start

Note

On the target host, WinRM must be enabled and the account must have sufficient privileges. Windows Server 2012 and later have WinRM enabled by default and an administrator account works with no configuration; Windows 10 / 11, non-administrator accounts, and local administrator accounts other than the built-in Administrator need host-side setup. See Preparing the Windows Host[9].

Everything starts with the fluent WinRMClient[10] builder — one client authenticates once and can run any number of queries and commands over the same connection:

import java.time.Duration;
import org.metricshub.winrm.WinRMClient;
import org.metricshub.winrm.WqlResult;
import org.metricshub.winrm.WqlRow;

public class Example {

    public static void main(String[] args) {
        try (WinRMClient client = WinRMClient.builder("server.example.com")
                .credentials("DOMAIN\\Administrator", "the-password".toCharArray())
                .timeout(Duration.ofSeconds(30))
                .build()) {

            WqlResult result = client.wql("SELECT Name, State FROM Win32_Service").execute();

            System.out.println(result.columns());       // [Name, State]
            for (WqlRow row : result) {
                System.out.println(row.string("Name") + " is " + row.string("State"));
            }
        }
    }
}

Remote commands work the same way:

CommandResult result = client.command("ipconfig /all").execute();
System.out.println(result.stdout());

And so do PowerShell scripts — delivered base64-encoded (-EncodedCommand), so they need no quoting or escaping at all:

CommandResult ps = client.powerShell("Get-Service | Where-Object Status -eq 'Running'").execute();

Remote files go through the same connection — no SMB, no extra port:

String tail = client.file("D:\\logs\\app.log").offset(-8192).readText(StandardCharsets.UTF_8);
RemoteFileList logs = client.file("D:\\logs").list().glob("*.log").recursive().execute();

Failures are reported through the unchecked WinRMClientException[11] hierarchy. The static one-shot helpers that predate WinRMClient (WinRMWqlExecutor.executeWql(...)[12], WinRMCommandExecutor.execute(...)[13]) remain available and unchanged, with their checked exceptions.

Client options

build() does not connect: the first operation does. A client may be shared between threads, but its connection is a serial channel: operations run one at a time, and an open stream or process holds the connection until it is closed. For parallel work, use one client per concurrent task.

Besides the host name passed to builder(...), only credentials(...) is mandatory on the builder[14]:

Option Default Details
credentials(String, char[]) required User name and domain[15]
https() / http(), port(int) HTTP; port 5985 (5986 with HTTPS) TLS / HTTPS[16]
authentication(AuthScheme...) NTLM Authentication[5]
ticketCache(Path), allowDelegation() none, off Kerberos[17], Credential delegation[18]
sslContext(SSLContext) / trustAllCertificates() JDK trust store, hostname verified TLS / HTTPS[16]
timeout(Duration) 30 s Timeouts and Errors[19]
retries(int, Duration) no retry Retrying[20]
namespace(String) ROOT\CIMV2 Choosing a namespace[21]
loadUserProfile() not loaded Loading the user profile[22]
maxCommandsPerShell(int) 10 Shell reuse[23]
consoleCodePage(int) 65001 (UTF-8) Input encoding[24]
arraySeparator(String) \| Reading the result[25]

Where to go next

  • Installation[8] — coordinates, supported JDKs, and the standalone CLI jar
  • Preparing the Windows Host[9] — prerequisites on the target: enabling WinRM and the privileges the account needs
  • WQL Queries[1] — query WMI and read the result
  • Remote Commands[2] — run commands and copy files to the host
  • File Transfers[26] — how files are copied to the host and downloaded back through the WinRM channel
  • Remote Files[3] — read remote files (whole, byte ranges, tails, streams, digests), get file properties, list directories
  • Command-Line Client[4] — the standalone jar's manual page
  • Authentication[5] — NTLM, Kerberos (including credential delegation), and Basic
  • TLS / HTTPS[16] — certificate validation and trust stores
  • Timeouts and Errors[19] — timeout semantics and the exception surface
  • Migrating from 1.x[6] — the 2.0.00 breaking changes, and moving to the fluent API
  • Migrating from winrm4j[27] — moving from cloudsoft/winrm4j: option mapping and behavioral differences
  • Legacy API[28] — the static one-shot helpers that predate WinRMClient
winrm java client windows remote management wsman dependency-free overview winrm wql wmi windows ntlm kerberos java remote management
Links:
  • [1] wql.html
  • [2] commands.html
  • [3] files.html
  • [4] cli.html
  • [5] authentication.html
  • [6] migrating-from-1x.html
  • [7] https://central.sonatype.com/artifact/org.metricshub/winrm-java
  • [8] installation.html
  • [9] preparing-the-host.html
  • [10] apidocs/org/metricshub/winrm/WinRMClient.html
  • [11] apidocs/org/metricshub/winrm/exceptions/WinRMClientException.html
  • [12] apidocs/org/metricshub/winrm/wql/WinRMWqlExecutor.html
  • [13] apidocs/org/metricshub/winrm/command/WinRMCommandExecutor.html
  • [14] apidocs/org/metricshub/winrm/WinRMClient.Builder.html
  • [15] authentication.html#user-name-and-domain
  • [16] tls.html
  • [17] authentication.html#kerberos-spnego
  • [18] authentication.html#credential-delegation
  • [19] timeouts-and-errors.html
  • [20] timeouts-and-errors.html#retrying-transient-connection-failures
  • [21] wql.html#choosing-a-namespace
  • [22] commands.html#loading-the-user-profile
  • [23] commands.html#shell-reuse
  • [24] commands.html#input-encoding
  • [25] wql.html#reading-the-result
  • [26] file-transfers.html
  • [27] migrating-from-winrm4j.html
  • [28] legacy.html
Searching...
No results.