#59 Fix Windows SMART retrieval with persistent elevated agent and Win32 device probing - #220
Conversation
…device probing - Enhanced getSmartDirect to probe /dev/pdN, pdN, and Win32 PhysicalDrive paths with -d nvme / -d sat hints, with fallback to error-JSON. - Replaced single-shot UAC escalation with a persistent elevated PowerShell agent running via IPC in %LOCALAPPDATA%\JDiskMark. - Fixed Start-Process argument quoting in SmartEscalation to handle paths with spaces.
There was a problem hiding this comment.
Pull request overview
This PR improves Windows SMART retrieval by introducing a persistent elevated PowerShell agent (reducing repeated UAC prompts) and by expanding device probing to include Win32 PhysicalDrive paths with NVMe/SAT hints, plus a JSON fallback path when device-open fails.
Changes:
- Replaced per-query UAC elevation with a persistent elevated PowerShell agent using file-based IPC in
%LOCALAPPDATA%\JDiskMark. - Added multi-pass device candidate probing on Windows, including
\\.\PhysicalDriveNwith-d nvme/-d sathints. - Added “error-JSON” fallback handling when smartctl returns JSON but sets the “device open failed” exit-code bit.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| jdm-core/src/main/java/jdiskmark/SmartEscalation.java | Implements the persistent elevated PowerShell agent, IPC protocol, and timeouts/shutdown handling. |
| jdm-core/src/main/java/jdiskmark/Smart.java | Expands Windows probing candidates and adds error-JSON fallback behavior in the direct execution path. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| Path scriptFile = ipcDir.resolve("smart-agent.ps1"); | ||
| Files.writeString(scriptFile, script, StandardCharsets.UTF_8); | ||
| String scriptPs = scriptFile.toString().replace("'", "''"); |
There was a problem hiding this comment.
@IanReyes44 what do you think about this solution: instead of generating this script where another user can modify it we just create a hard version control script that is installed along with our app which will require admin to modify it. in the source repo we can place it in jdm-core/src/main/resources/smartctl/smart-agent.ps1 when we're installing after smartctl folder is expanded we can copy this src file to:
Program Files/JDiskMark/app/smartctl/
├── smartctl.exe
├── smart-agent.ps1 ← here
└── ...
the current generated script has some dynamic elements so we'd either have to pass those in as parameters or have the script automatically calculate that.
jamesmarkchan
left a comment
There was a problem hiding this comment.
That security finding from copilot makes sense and can be addressed by making the script live in the installation dir. like C:\Program Files\JDiskMark 0.8.0\....
if this change sounds good we should be able to get this into the next release!
the other two findings from copilot also make sense to do.
one more thing! we allow on windows to run multiple versions, how about changing the folder location where these messages are passed back and forth to <userhome>/.jdm/<install_version>/
- Fix PowerShell -ArgumentList quoting (Copilot medium): switch from
inline string escaping to Base64-encoded -EncodedCommand so paths
containing spaces or special characters are never exposed to
Start-Process argument-list parsing
- Fix Win32 PhysicalDrive probe guard (Copilot medium): tighten
startsWith('pd') to matches('^pd\d+$') so only valid numeric
device names (pd0, pd1...) generate \\.\PhysicalDriveN paths
- Fix agent script security (Copilot high / jamesmarkchan): move
smart-agent.ps1 from the user-writable %LOCALAPPDATA% temp dir to
a static resource bundled alongside smartctl.exe in Program Files
(admin-write-only). Eliminates the privilege escalation window where
a same-user process could tamper with the script between write and
elevation.
- Version-scope the IPC directory (jamesmarkchan): change IPC dir
from %LOCALAPPDATA%\JDiskMark to ~/.jdm/<install_version>/smart-ipc
(matching App.APP_CACHE_DIR) so side-by-side installs of different
versions do not share or interfere with each other's IPC files.
Files changed:
jdm-core/pom.xml - copy smart-agent.ps1 into target/smartctl/ during build
jdm-core/src/main/resources/smartctl/ - new static smart-agent.ps1 with param block
jdm-core/src/main/java/jdiskmark/SmartEscalation.java - all of the above
jdm-core/src/main/java/jdiskmark/Smart.java - Javadoc update
|
Hi @jamesmarkchan, All feedback has been addressed in commit 4ab0033: Admin-only script location: Bundled smart-agent.ps1 into the installation directory alongside smartctl.exe instead of writing to %LOCALAPPDATA%. |

Summary
This PR addresses Windows SMART data retrieval failures and improves the user experience by replacing per-query UAC prompts with a persistent elevated background agent and enhancing device path probing with NVMe/SAT hints.
Key Changes
1. Persistent Elevated Background Agent (
SmartEscalation.java)%LOCALAPPDATA%\JDiskMarkusing request (smart-req-<device>.txt), status (smart-ipc-<device>.status), and result (smart-ipc-<device>.json) files encoded in UTF-8 without BOM.smart-agent-stopper) that dropssmart-agent-stop.txtto cleanly terminate the elevated agent process upon application exit.Start-Processargument quoting in PowerShell invocation to correctly handle paths with spaces.2. Multi-Pass Device Probing & Fallback (
Smart.java&SmartEscalation.java)/dev/pdNand barepdN).\\.\PhysicalDriveN) with plain,-d nvme, and-d sathints to ensure support across NVMe controllers and SAT devices on Windows.smartctlexit code), the parser retains and returns the first available JSON output, allowing the UI to extract drive identity (model, serial number, firmware) even if SMART attribute reading is restricted.Verification
mvn clean install -pl jdm-core -am --no-transfer-progress.