Skip to content

Use JNA/WMI instead of PowerShell to list Windows processes - #4718

Draft
janhoy wants to merge 2 commits into
apache:mainfrom
janhoy:jna-wmi-windows-cmdline
Draft

Use JNA/WMI instead of PowerShell to list Windows processes#4718
janhoy wants to merge 2 commits into
apache:mainfrom
janhoy:jna-wmi-windows-cmdline

Conversation

@janhoy

@janhoy janhoy commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

On Windows, SolrProcessManager (used by the bin/solr status CLI) discovers running Solr processes by reading each Java process's command line. Since ProcessHandle does not expose command lines on Windows, it previously spawned powershell.exe running Get-CimInstance -ClassName Win32_Process ... | ConvertTo-Json and parsed the JSON.

This PR replaces that with a direct WMI (Win32_Process) query via JNA (jna-platform), so no external process is spawned and PowerShell no longer needs to be present/enabled.

Changes

  • Add net.java.dev.jna:jna-platform to solr-core.
  • Rewrite commandLinesWindows() to use CoInitializeExWmiQueryCoUninitialize; drop the PowerShell JSON parsing helper and its unit test.
  • Tighten the test security policy: remove the broad <<ALL FILES>> execute grant (only needed to exec powershell) and add the JNA native-library load / jna.* property-read permissions instead.

Notes

  • The WMI code path is Windows-only (Constants.WINDOWS); Linux/macOS behaviour is unchanged and all static checks + SolrProcessManagerTest pass. The live WMI query has not been exercised on real Windows yet.

Draft pending validation on a Windows runner.

SolrProcessManager previously spawned a powershell.exe process running
Get-CimInstance to obtain command lines of Java processes on Windows.
Replace this with a WMI (Win32_Process) query via JNA, avoiding an
external process spawn and the dependency on PowerShell being present.

- Add net.java.dev.jna:jna-platform dependency to solr-core
- Drop the PowerShell JSON parsing helper and its test
- Remove the broad "<<ALL FILES>>" execute grant from the test security
  policy (only needed to exec powershell) and add the JNA native-library
  load / jna.* property-read permissions instead
Comment on lines +195 to +201
new WmiQuery<>("Win32_Process", ProcessProperty.class).execute();
Map<Long, String> pidToCommandLine = new HashMap<>();
for (int i = 0; i < result.getResultCount(); i++) {
Object name = result.getValue(ProcessProperty.NAME, i);
if (name == null || !name.toString().toLowerCase(Locale.ROOT).contains("java")) {
continue;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question on the query: it doesn't push the java filter into the WQL itself. JNA's WmiQuery javadoc notes the class name may include a WHERE clause with filtering conditions. so "Win32_Process WHERE NAME LIKE '%java%'" would let WMI do the filtering and make the name check in the loop redundant. Also, the LIKE is case-insensitive according to MS-WMI, so it should match the old -like '*java*' behaviour.

(I noticed this is still a draft, so ignore it if this is already on your radar.)

Suggested change
new WmiQuery<>("Win32_Process", ProcessProperty.class).execute();
Map<Long, String> pidToCommandLine = new HashMap<>();
for (int i = 0; i < result.getResultCount(); i++) {
Object name = result.getValue(ProcessProperty.NAME, i);
if (name == null || !name.toString().toLowerCase(Locale.ROOT).contains("java")) {
continue;
}
new WmiQuery<>("Win32_Process WHERE NAME LIKE '%java%'", ProcessProperty.class).execute();
Map<Long, String> pidToCommandLine = new HashMap<>();
for (int i = 0; i < result.getResultCount(); i++) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not on my radar, definitely an improvement. Do you by chance have a Windows system to test on?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am on Mac (M-series), so no native windows, but happy to spin up a windows 11 ARM VM and test it out. Will report back later.

Although it will be aarch64 rather than x86-64, that shouldn't affect the WQL semantics.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janhoy, I have tested the WHERE clause works through WmiQuery and matching is case-insensitive.

Environment: Windows 11 VM, amd64, JNA 5.19.1, with two java processes running

no filter    -> 144 rows
      System Idle Process
      System
      Registry
      smss.exe
      ...
'%java%'     -> 2 rows
      java.exe
      java.exe
'%JAVA%'     -> 2 rows
      java.exe
      java.exe
'%Java%'     -> 2 rows
      java.exe
      java.exe
Name         -> 2 rows
      java.exe
      java.exe
NAME upper   -> 2 rows
      java.exe
      java.exe
name lower   -> 2 rows
      java.exe
      java.exe

All three literal casings return the same rows, so it matches the old -like '*java*' behaviour. Property name casing doesn't matter either: Name, NAME & name.

Correction: I said aarch64 earlier but I ended up on the x64 JDK, so it loaded JNA's win32-x86-64 native under emulation which is closer to the usual deployment.

Happy to share the probe if this is helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants