-
Notifications
You must be signed in to change notification settings - Fork 68
#1869: Improve windows helper to search windows registry #1876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
faa6b1b
53fff3f
d123088
7c8f432
9693b95
ccb14d3
8b4d51d
a35910b
68e09fc
6ed1306
2d40318
e05473a
af4ddbc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,6 +21,13 @@ public class WindowsHelperImpl implements WindowsHelper { | |||||
| /** Registry key for the users environment variables. */ | ||||||
| public static final String HKCU_ENVIRONMENT = "HKCU\\Environment"; | ||||||
|
|
||||||
| /** Common Windows registry base paths containing (uninstall) information for installed applications (system-wide and per-user). */ | ||||||
| private static final String[] REGISTRY_BASE_PATHS = { | ||||||
| "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", | ||||||
| "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", | ||||||
| "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" | ||||||
| }; | ||||||
|
|
||||||
| private final IdeContext context; | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -60,13 +67,80 @@ public String getUserEnvironmentValue(String key) { | |||||
| @Override | ||||||
| public String getRegistryValue(String path, String key) { | ||||||
|
|
||||||
| ProcessResult result = this.context.newProcess().errorHandling(ProcessErrorHandling.LOG_WARNING).executable("reg").addArgs("query", path, "/v", key) | ||||||
| List<String> out = runReg("query", path, "/v", key); | ||||||
| if (out != null) { | ||||||
| return retrieveRegString(key, out); | ||||||
| } | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public String getDisplayVersionFromRegistry(String appName) { | ||||||
| return getRegistryValueBySearch(appName, "DisplayVersion"); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public String getDisplayIconFromRegistry(String appName) { | ||||||
| return getRegistryValueBySearch(appName, "DisplayIcon"); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public String getUninstallStringFromRegistry(String appName) { | ||||||
| return getRegistryValueBySearch(appName, "UninstallString"); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public String getInstallLocationFromRegistry(String appName) { | ||||||
| return getRegistryValueBySearch(appName, "InstallLocation"); | ||||||
| } | ||||||
|
|
||||||
| private String getRegistryValueBySearch(String appName, String key) { | ||||||
|
|
||||||
| String uninstallKey = findUninstallKey(appName); | ||||||
| if (uninstallKey == null) { | ||||||
| return null; | ||||||
| } | ||||||
| List<String> out = runReg("query", uninstallKey); | ||||||
| if (out != null) { | ||||||
| return retrieveRegString(key, out); | ||||||
| } | ||||||
| return null; | ||||||
| } | ||||||
|
|
||||||
| private String findUninstallKey(String appName) { | ||||||
|
|
||||||
| for (String registryBasePath : REGISTRY_BASE_PATHS) { | ||||||
| List<String> out = runReg("query", registryBasePath, "/s", "/f", appName); | ||||||
|
hohwille marked this conversation as resolved.
|
||||||
| if (out == null) { | ||||||
| continue; | ||||||
| } | ||||||
| for (String line : out) { | ||||||
| line = line.trim(); | ||||||
| if (line.startsWith("HKEY_")) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The output of That means the |
||||||
| return line; // exact registry path (key) for tool | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| return null; | ||||||
|
|
||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Executes a Windows registry command and returns its output. | ||||||
| * | ||||||
| * @param args the registry command arguments. | ||||||
| * @return the command output lines, or {@code null} if the command failed | ||||||
| */ | ||||||
| protected List<String> runReg(String... args) { | ||||||
| ProcessResult result = this.context.newProcess() | ||||||
| .errorHandling(ProcessErrorHandling.LOG_WARNING) | ||||||
| .executable("reg") | ||||||
| .addArgs(args) | ||||||
| .run(ProcessMode.DEFAULT_CAPTURE); | ||||||
| if (!result.isSuccessful()) { | ||||||
| return null; | ||||||
| } | ||||||
| List<String> out = result.getOut(); | ||||||
| return retrieveRegString(key, out); | ||||||
| return result.getOut(); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package com.devonfw.tools.ide.os; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import com.devonfw.tools.ide.context.IdeContext; | ||
|
|
||
| /** | ||
| * Test-specific subclass of {@link WindowsHelperImpl}. | ||
| * | ||
| * <p> | ||
| * Mainly used as a test seam to simulate the reg.exe command for test purposes. | ||
| * </p> | ||
| */ | ||
| public class WindowsHelperImplTestable extends WindowsHelperImpl { | ||
|
|
||
| /** | ||
| * The constructor. | ||
| * | ||
| * @param context the {@link IdeContext}. | ||
| */ | ||
| public WindowsHelperImplTestable(IdeContext context) { | ||
|
|
||
| super(context); | ||
| } | ||
|
|
||
| @Override | ||
| protected List<String> runReg(String... args) { | ||
|
jakozian marked this conversation as resolved.
|
||
|
|
||
| String searchValue = extractFilterValue(args); | ||
| // Case: reg query <basePath> /s /f <appName> | ||
| if (searchValue != null) { | ||
| if (!"TestApp".equalsIgnoreCase(searchValue)) { | ||
| return List.of(); | ||
| } | ||
| return List.of( | ||
| "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TestApp", | ||
| " DisplayName REG_SZ TestApp" | ||
| ); | ||
| } | ||
| // Case: reg query <exactKey> | ||
| if (args.length >= 2 && | ||
| args[0].equalsIgnoreCase("query") && | ||
| args[1].endsWith("\\Uninstall\\TestApp")) { | ||
|
|
||
| return List.of( | ||
| "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TestApp", | ||
| " DisplayName REG_SZ TestApp", | ||
| " DisplayVersion REG_SZ 1.1.1", | ||
| " DisplayIcon REG_SZ C:\\Program Files\\TestApp\\testapp.exe,0", | ||
| " InstallLocation REG_SZ C:\\Program Files\\TestApp", | ||
| " UninstallString REG_SZ \"C:\\Program Files\\TestApp\\uninstall.exe\"" | ||
| ); | ||
| } | ||
|
|
||
| return List.of(); | ||
| } | ||
|
|
||
|
|
||
| private static String extractFilterValue(String[] args) { | ||
|
|
||
| for (int i = 0; i < args.length - 1; i++) { | ||
| if ("/f".equalsIgnoreCase(args[i])) { | ||
| return args[i + 1]; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| package com.devonfw.tools.ide.os; | ||
|
|
||
| import java.util.List; | ||
| import java.util.Properties; | ||
|
|
||
| import com.devonfw.tools.ide.context.IdeContext; | ||
|
|
@@ -11,6 +12,18 @@ public class WindowsHelperMock extends WindowsHelperImpl { | |
|
|
||
| private final Properties env; | ||
|
|
||
| private static final String MOCK_APP_NAME = "TestApp"; | ||
|
|
||
| private static final String MOCK_DISPLAY_VERSION = "1.1.1"; | ||
|
|
||
| private static final String MOCK_INSTALL_LOCATION = "C:\\Program Files\\TestApp"; | ||
|
|
||
| private static final String MOCK_DISPLAY_ICON = | ||
| "C:\\Program Files\\TestApp\\testapp.exe,0"; | ||
| private static final String MOCK_UNINSTALL_STRING = | ||
| "\"C:\\Program Files\\TestApp\\uninstall.exe\""; | ||
|
Comment on lines
+15
to
+24
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for mocking we should use a |
||
|
|
||
|
|
||
| /** | ||
| * The constructor. | ||
| */ | ||
|
|
@@ -41,6 +54,26 @@ public String getUserEnvironmentValue(String key) { | |
| return this.env.getProperty(key); | ||
| } | ||
|
|
||
| @Override | ||
| public String getDisplayVersionFromRegistry(String appName) { | ||
| return matchesApp(appName) ? MOCK_DISPLAY_VERSION : null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getDisplayIconFromRegistry(String appName) { | ||
| return matchesApp(appName) ? MOCK_DISPLAY_ICON : null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getUninstallStringFromRegistry(String appName) { | ||
| return matchesApp(appName) ? MOCK_UNINSTALL_STRING : null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getInstallLocationFromRegistry(String appName) { | ||
| return matchesApp(appName) ? MOCK_INSTALL_LOCATION : null; | ||
| } | ||
|
|
||
| @Override | ||
| public String getRegistryValue(String path, String key) { | ||
|
|
||
|
|
@@ -51,4 +84,51 @@ public String getRegistryValue(String path, String key) { | |
| } | ||
| return null; | ||
| } | ||
|
|
||
| private boolean matchesApp(String appName) { | ||
| return appName != null | ||
| && appName.equalsIgnoreCase(MOCK_APP_NAME); | ||
| } | ||
|
|
||
| @Override | ||
| protected List<String> runReg(String... args) { | ||
|
|
||
| String searchValue = extractFilterValue(args); | ||
| // Case: reg query <basePath> /s /f <appName> | ||
| if (searchValue != null) { | ||
| if (!"TestApp".equalsIgnoreCase(searchValue)) { | ||
| return List.of(); | ||
| } | ||
| return List.of( | ||
| "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TestApp", | ||
| " DisplayName REG_SZ TestApp" | ||
| ); | ||
| } | ||
| // Case: reg query <exactKey> | ||
| if (args.length >= 2 && | ||
| args[0].equalsIgnoreCase("query") && | ||
| args[1].endsWith("\\Uninstall\\TestApp")) { | ||
|
|
||
| return List.of( | ||
| "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\TestApp", | ||
| " DisplayName REG_SZ TestApp", | ||
| " DisplayVersion REG_SZ 1.1.1", | ||
| " DisplayIcon REG_SZ C:\\Program Files\\TestApp\\testapp.exe,0", | ||
| " InstallLocation REG_SZ C:\\Program Files\\TestApp", | ||
| " UninstallString REG_SZ \"C:\\Program Files\\TestApp\\uninstall.exe\"" | ||
| ); | ||
| } | ||
|
|
||
| return List.of(); | ||
| } | ||
|
|
||
| private static String extractFilterValue(String[] args) { | ||
|
|
||
| for (int i = 0; i < args.length - 1; i++) { | ||
| if ("/f".equalsIgnoreCase(args[i])) { | ||
| return args[i + 1]; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| } | ||

Uh oh!
There was an error while loading. Please reload this page.