• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 25431217639

06 May 2026 10:58AM UTC coverage: 70.703% (-0.03%) from 70.728%
25431217639

Pull #1876

github

web-flow
Merge e05473ad9 into 2e54dfef7
Pull Request #1876: #1869: Improve windows helper to search windows registry

4410 of 6892 branches covered (63.99%)

Branch coverage included in aggregate %.

11373 of 15431 relevant lines covered (73.7%)

3.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.76
cli/src/main/java/com/devonfw/tools/ide/os/WindowsHelperImpl.java
1
package com.devonfw.tools.ide.os;
2

3
import java.util.List;
4

5
import org.slf4j.Logger;
6
import org.slf4j.LoggerFactory;
7

8
import com.devonfw.tools.ide.context.IdeContext;
9
import com.devonfw.tools.ide.log.IdeLogLevel;
10
import com.devonfw.tools.ide.process.ProcessErrorHandling;
11
import com.devonfw.tools.ide.process.ProcessMode;
12
import com.devonfw.tools.ide.process.ProcessResult;
13

14
/**
15
 * Implementation of {@link WindowsHelper}.
16
 */
17
public class WindowsHelperImpl implements WindowsHelper {
18

19
  private static final Logger LOG = LoggerFactory.getLogger(WindowsHelperImpl.class);
3✔
20

21
  /** Registry key for the users environment variables. */
22
  public static final String HKCU_ENVIRONMENT = "HKCU\\Environment";
23

24
  /** Common Windows registry base paths containing (uninstall) information for installed applications (system-wide and per-user). */
25
  private static final String[] REGISTRY_BASE_PATHS = {
16✔
26
      "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
27
      "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
28
      "HKLM\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
29
  };
30

31
  private final IdeContext context;
32

33
  /**
34
   * The constructor.
35
   *
36
   * @param context the {@link IdeContext}.
37
   */
38
  public WindowsHelperImpl(IdeContext context) {
2✔
39

40
    this.context = context;
3✔
41
  }
1✔
42

43
  @Override
44
  public void setUserEnvironmentValue(String key, String value) {
45

46
    ProcessResult result = this.context.newProcess().executable("setx").addArgs(key, value).run(ProcessMode.DEFAULT_SILENT);
×
47
    assert (result.isSuccessful());
×
48
  }
×
49

50
  @Override
51
  public void removeUserEnvironmentValue(String key) {
52
    ProcessResult result = this.context.newProcess().executable("reg").addArgs("delete", HKCU_ENVIRONMENT, "/v", key, "/f")
×
53
        .errorHandling(ProcessErrorHandling.LOG_WARNING).run(ProcessMode.DEFAULT_CAPTURE);
×
54
    if (result.isSuccessful()) {
×
55
      LOG.debug("Removed environment variable {}", key);
×
56
    } else {
57
      result.log(IdeLogLevel.WARNING);
×
58
    }
59
  }
×
60

61
  @Override
62
  public String getUserEnvironmentValue(String key) {
63

64
    return getRegistryValue(HKCU_ENVIRONMENT, key);
×
65
  }
66

67
  @Override
68
  public String getRegistryValue(String path, String key) {
69

70
    List<String> out = runReg("query", path, "/v", key);
×
71
    if (out != null) {
×
72
      return retrieveRegString(key, out);
×
73
    }
74
    return null;
×
75
  }
76

77
  @Override
78
  public String getDisplayVersionFromRegistry(String appName) {
79
    return getRegistryValueBySearch(appName, "DisplayVersion");
5✔
80
  }
81

82
  @Override
83
  public String getDisplayIconFromRegistry(String appName) {
84
    return getRegistryValueBySearch(appName, "DisplayIcon");
5✔
85
  }
86

87
  @Override
88
  public String getUninstallStringFromRegistry(String appName) {
89
    return getRegistryValueBySearch(appName, "UninstallString");
5✔
90
  }
91

92
  @Override
93
  public String getInstallLocationFromRegistry(String appName) {
94
    return getRegistryValueBySearch(appName, "InstallLocation");
5✔
95
  }
96

97
  private String getRegistryValueBySearch(String appName, String key) {
98

99
    String uninstallKey = findUninstallKey(appName);
4✔
100
    if (uninstallKey == null) {
2✔
101
      return null;
2✔
102
    }
103
    List<String> out = runReg("query", uninstallKey);
13✔
104
    if (out != null) {
2!
105
      return retrieveRegString(key, out);
5✔
106
    }
107
    return null;
×
108
  }
109

110
  private String findUninstallKey(String appName) {
111

112
    for (String registryBasePath : REGISTRY_BASE_PATHS) {
16✔
113
      List<String> out = runReg("query", registryBasePath, "/s", "/f", appName);
25✔
114
      if (out == null) {
2!
115
        continue;
×
116
      }
117
      for (String line : out) {
10✔
118
        line = line.trim();
3✔
119
        if (line.startsWith("HKEY_")) {
4!
120
          return line; // exact registry path (key) for tool
2✔
121
        }
122
      }
×
123
    }
124
    return null;
2✔
125

126
  }
127

128
  /**
129
   * Executes a Windows registry command and returns its output.
130
   *
131
   * @param args the registry command arguments.
132
   * @return the command output lines, or {@code null} if the command failed
133
   */
134
  protected List<String> runReg(String... args) {
135
    ProcessResult result = this.context.newProcess()
×
136
        .errorHandling(ProcessErrorHandling.LOG_WARNING)
×
137
        .executable("reg")
×
138
        .addArgs(args)
×
139
        .run(ProcessMode.DEFAULT_CAPTURE);
×
140
    if (!result.isSuccessful()) {
×
141
      return null;
×
142
    }
143
    return result.getOut();
×
144
  }
145

146
  /**
147
   * Parses the result of a registry query and outputs the given key.
148
   *
149
   * @param key the key to look for.
150
   * @param out List of keys from registry query result.
151
   * @return the registry value.
152
   */
153
  protected String retrieveRegString(String key, List<String> out) {
154
    for (String line : out) {
10✔
155
      int i = line.indexOf(key);
4✔
156
      if (i >= 0) {
2✔
157
        assert (i == 4);
4!
158
        i += key.length();
5✔
159
        i = skipWhitespaces(line, i);
4✔
160
        i = skipNonWhitespaces(line, i); // the type (e.g. "REG_SZ")
4✔
161
        i = skipWhitespaces(line, i);
4✔
162
        line = line.substring(i);
4✔
163
        return line;
2✔
164
      }
165
    }
1✔
166
    return null;
2✔
167
  }
168

169
  private static int skipWhitespaces(String string, int i) {
170

171
    int len = string.length();
3✔
172
    while ((i < len) && Character.isWhitespace(string.charAt(i))) {
8!
173
      i++;
2✔
174
    }
175
    return i;
2✔
176
  }
177

178
  private static int skipNonWhitespaces(String string, int i) {
179

180
    int len = string.length();
3✔
181
    while ((i < len) && !Character.isWhitespace(string.charAt(i))) {
8!
182
      i++;
2✔
183
    }
184
    return i;
2✔
185
  }
186

187
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc