You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2026/02/21 20:26:15 UTC
(maven-surefire) branch windows-wmic created (now 549ad0d4c)
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a change to branch windows-wmic
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
at 549ad0d4c Supporting WMIC and PowerShell
This branch includes the following new commits:
new 549ad0d4c Supporting WMIC and PowerShell
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(maven-surefire) 01/01: Supporting WMIC and PowerShell
Posted by ti...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch windows-wmic
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit 549ad0d4ce213c98d8507e678676bdc1fa45b0dd
Author: tibordigana <ti...@apache.org>
AuthorDate: Sat Feb 21 21:25:30 2026 +0100
Supporting WMIC and PowerShell
---
.../apache/maven/surefire/booter/PpidChecker.java | 92 +++++++++++++++-------
.../apache/maven/surefire/booter/ProcessInfo.java | 3 +-
.../maven/surefire/booter/PpidCheckerTest.java | 2 +-
3 files changed, 68 insertions(+), 29 deletions(-)
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
index 2c836ea21..0100cd78e 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
@@ -23,6 +23,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
+import java.math.BigDecimal;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Queue;
@@ -62,17 +63,23 @@
* @since 2.20.1
*/
final class PpidChecker {
+ private static final BigDecimal THOUSAND = new BigDecimal(1000);
private static final long MINUTES_TO_MILLIS = 60L * 1000L;
// 25 chars https://superuser.com/questions/937380/get-creation-time-of-file-in-milliseconds/937401#937401
private static final int WMIC_CREATION_DATE_VALUE_LENGTH = 25;
private static final int WMIC_CREATION_DATE_TIMESTAMP_LENGTH = 18;
private static final SimpleDateFormat WMIC_CREATION_DATE_FORMAT =
IS_OS_WINDOWS ? createWindowsCreationDateFormat() : null;
+ private static final Pattern POWERSHELL_CPU_PATTERN = Pattern.compile("^\\d+(\\.\\d+)?$");
private static final String WMIC_CREATION_DATE = "CreationDate";
+ private static final String POWERSHELL_CMD_HEADER = "CPU";
private static final String WINDOWS_SYSTEM_ROOT_ENV = "SystemRoot";
- private static final String RELATIVE_PATH_TO_WMIC = "System32\\Wbem";
- private static final String SYSTEM_PATH_TO_WMIC =
- "%" + WINDOWS_SYSTEM_ROOT_ENV + "%\\" + RELATIVE_PATH_TO_WMIC + "\\";
+ private static final String RELATIVE_PATH_TO_WMIC32 = "System32\\Wbem";
+ private static final String RELATIVE_PATH_TO_WMIC64 = "SysWOW64\\Wbem";
+ private static final String SYSTEM_PATH_TO_WMIC32 =
+ "%" + WINDOWS_SYSTEM_ROOT_ENV + "%\\" + RELATIVE_PATH_TO_WMIC32 + "\\";
+ private static final String SYSTEM_PATH_TO_WMIC64 =
+ "%" + WINDOWS_SYSTEM_ROOT_ENV + "%\\" + RELATIVE_PATH_TO_WMIC64 + "\\";
private static final String PS_ETIME_HEADER = "ELAPSED";
private static final String PS_PID_HEADER = "PID";
@@ -159,7 +166,7 @@ ProcessInfo unix() {
ProcessInfoConsumer reader = new ProcessInfoConsumer(charset) {
@Override
@Nonnull
- ProcessInfo consumeLine(String line, ProcessInfo previousOutputLine) {
+ protected ProcessInfo consumeLine(String line, ProcessInfo previousOutputLine) {
if (previousOutputLine.isInvalid()) {
if (hasHeader) {
Matcher matcher = UNIX_CMD_OUT_PATTERN.matcher(line);
@@ -187,36 +194,61 @@ ProcessInfo consumeLine(String line, ProcessInfo previousOutputLine) {
}
ProcessInfo windows() {
- ProcessInfoConsumer reader = new ProcessInfoConsumer("US-ASCII") {
+ class WindowsProcessInfoConsumer extends ProcessInfoConsumer {
+ private boolean isPowershell;
+
+ WindowsProcessInfoConsumer() {
+ super("US-ASCII");
+ }
+
@Override
@Nonnull
- ProcessInfo consumeLine(String line, ProcessInfo previousProcessInfo) throws Exception {
+ protected ProcessInfo consumeLine(String line, ProcessInfo previousProcessInfo) throws Exception {
if (previousProcessInfo.isInvalid() && !line.isEmpty()) {
if (hasHeader) {
- // now the line is CreationDate, e.g. 20180406142327.741074+120
- if (line.length() != WMIC_CREATION_DATE_VALUE_LENGTH) {
- throw new IllegalStateException("WMIC CreationDate should have 25 characters " + line);
+ if (isPowershell) {
+ if (POWERSHELL_CPU_PATTERN.matcher(line).matches()) {
+ long etime = new BigDecimal(line).multiply(THOUSAND).longValue();
+ return windowsProcessInfo(ppid, etime);
+ }
+ } else {
+ // now the line is CreationDate, e.g. 20180406142327.741074+120
+ if (line.length() != WMIC_CREATION_DATE_VALUE_LENGTH) {
+ throw new IllegalStateException("WMIC CreationDate should have 25 characters " + line);
+ }
+ String startTimestamp = line.substring(0, WMIC_CREATION_DATE_TIMESTAMP_LENGTH);
+ int indexOfTimeZone = WMIC_CREATION_DATE_VALUE_LENGTH - 4;
+ long startTimestampMillisUTC = WMIC_CREATION_DATE_FORMAT.parse(startTimestamp).getTime()
+ - parseInt(line.substring(indexOfTimeZone)) * MINUTES_TO_MILLIS;
+ return windowsProcessInfo(ppid, startTimestampMillisUTC);
}
- String startTimestamp = line.substring(0, WMIC_CREATION_DATE_TIMESTAMP_LENGTH);
- int indexOfTimeZone = WMIC_CREATION_DATE_VALUE_LENGTH - 4;
- long startTimestampMillisUTC =
- WMIC_CREATION_DATE_FORMAT.parse(startTimestamp).getTime()
- - parseInt(line.substring(indexOfTimeZone)) * MINUTES_TO_MILLIS;
- return windowsProcessInfo(ppid, startTimestampMillisUTC);
} else {
- hasHeader = WMIC_CREATION_DATE.equals(line);
+ hasHeader = WMIC_CREATION_DATE.equals(line) || POWERSHELL_CMD_HEADER.equals(line);
}
}
return previousProcessInfo;
}
- };
- String wmicPath = hasWmicStandardSystemPath() ? SYSTEM_PATH_TO_WMIC : "";
- return reader.execute(
- "CMD",
- "/A",
- "/X",
- "/C",
- wmicPath + "wmic process where (ProcessId=" + ppid + ") get " + WMIC_CREATION_DATE);
+
+ ProcessInfo checkPpid() {
+ if (hasWmicStandardSystemPath64()) {
+ return execute("CMD", "/A", "/X", "/C",
+ SYSTEM_PATH_TO_WMIC64
+ + "wmic process where (ProcessId=" + ppid + ") get " + WMIC_CREATION_DATE);
+ } else if (hasWmicStandardSystemPath32()) {
+ return execute("CMD", "/A", "/X", "/C",
+ SYSTEM_PATH_TO_WMIC32
+ + "wmic process where (ProcessId=" + ppid + ") get " + WMIC_CREATION_DATE);
+ } else {
+ isPowershell = true;
+ return execute("CMD", "/A", "/X", "/C",
+ "powershell", " \"Get-Process -Id " + ppid + " | Select-Object -Property CPU" + "\"");
+ }
+ }
+ }
+
+ WindowsProcessInfoConsumer reader = new WindowsProcessInfoConsumer();
+ return reader.checkPpid();
+
}
void destroyActiveCommands() {
@@ -254,9 +286,14 @@ private static boolean canExecuteStandardUnixPs() {
}
}
- private static boolean hasWmicStandardSystemPath() {
+ private static boolean hasWmicStandardSystemPath32() {
+ String systemRoot = System.getenv(WINDOWS_SYSTEM_ROOT_ENV);
+ return isNotBlank(systemRoot) && new File(systemRoot, RELATIVE_PATH_TO_WMIC32 + "\\wmic.exe").isFile();
+ }
+
+ private static boolean hasWmicStandardSystemPath64() {
String systemRoot = System.getenv(WINDOWS_SYSTEM_ROOT_ENV);
- return isNotBlank(systemRoot) && new File(systemRoot, RELATIVE_PATH_TO_WMIC + "\\wmic.exe").isFile();
+ return isNotBlank(systemRoot) && new File(systemRoot, RELATIVE_PATH_TO_WMIC64 + "\\wmic.exe").isFile();
}
static long fromDays(Matcher matcher) {
@@ -337,7 +374,8 @@ abstract class ProcessInfoConsumer {
this.charset = charset;
}
- abstract @Nonnull ProcessInfo consumeLine(String line, ProcessInfo previousProcessInfo) throws Exception;
+ protected abstract @Nonnull ProcessInfo consumeLine(String line, ProcessInfo previousProcessInfo)
+ throws Exception;
ProcessInfo execute(String... command) {
ProcessBuilder processBuilder = new ProcessBuilder(command);
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java
index 771445965..11f77f852 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProcessInfo.java
@@ -34,6 +34,7 @@
final class ProcessInfo {
static final ProcessInfo INVALID_PROCESS_INFO = new ProcessInfo(null, 0);
static final ProcessInfo ERR_PROCESS_INFO = new ProcessInfo(null, 0);
+ static final ProcessInfo ERR_CMD_NOT_FOUND = new ProcessInfo(null, 0);
/**
* On Unix we do not get PID due to the command is interested only to etime of PPID:
@@ -65,7 +66,7 @@ boolean isInvalid() {
}
boolean isError() {
- return this == ERR_PROCESS_INFO;
+ return this == ERR_PROCESS_INFO || this == ERR_CMD_NOT_FOUND;
}
String getPID() {
diff --git a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
index 78f35716f..83e5f8dbe 100644
--- a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
+++ b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
@@ -371,7 +371,7 @@ public void shouldHaveSystemPathToWmicOnWindows() throws Exception {
assumeThat(System.getenv("SystemRoot"), is(not("")));
assumeTrue(new File(System.getenv("SystemRoot"), "System32\\Wbem").isDirectory());
assumeTrue(new File(System.getenv("SystemRoot"), "System32\\Wbem\\wmic.exe").isFile());
- assertThat((Boolean) invokeMethod(PpidChecker.class, "hasWmicStandardSystemPath"))
+ assertThat((Boolean) invokeMethod(PpidChecker.class, "hasWmicStandardSystemPath32"))
.isTrue();
assertThat(new File(System.getenv("SystemRoot"), "System32\\Wbem\\wmic.exe"))
.isFile();