1
2
3
4
5 package oshi.driver.windows.registry;
6
7 import com.sun.jna.platform.win32.Advapi32Util;
8 import com.sun.jna.platform.win32.Win32Exception;
9 import com.sun.jna.platform.win32.WinNT;
10 import com.sun.jna.platform.win32.WinReg;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import oshi.software.os.ApplicationInfo;
14 import oshi.util.ParseUtil;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.LinkedHashMap;
20 import java.util.LinkedHashSet;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.Arrays;
24
25 public final class InstalledAppsData {
26 private static final Logger LOG = LoggerFactory.getLogger(InstalledAppsData.class);
27
28 private InstalledAppsData() {
29 }
30
31 private static final Map<WinReg.HKEY, List<String>> REGISTRY_PATHS = new HashMap<>();
32 private static final int[] ACCESS_FLAGS = { WinNT.KEY_WOW64_64KEY, WinNT.KEY_WOW64_32KEY };
33
34 static {
35 REGISTRY_PATHS.put(WinReg.HKEY_LOCAL_MACHINE,
36 Arrays.asList("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
37 "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"));
38
39 REGISTRY_PATHS.put(WinReg.HKEY_CURRENT_USER,
40 Arrays.asList("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"));
41 }
42
43 public static List<ApplicationInfo> queryInstalledApps() {
44 Set<ApplicationInfo> appInfoSet = new LinkedHashSet<>();
45
46
47 for (Map.Entry<WinReg.HKEY, List<String>> entry : REGISTRY_PATHS.entrySet()) {
48 WinReg.HKEY rootKey = entry.getKey();
49 List<String> uninstallPaths = entry.getValue();
50
51 for (String registryPath : uninstallPaths) {
52 for (int accessFlag : ACCESS_FLAGS) {
53 String[] keys = Advapi32Util.registryGetKeys(rootKey, registryPath, accessFlag);
54 for (String key : keys) {
55 String fullPath = registryPath + "\\" + key;
56 try {
57 String name = getRegistryValueOrUnknown(rootKey, fullPath, "DisplayName", accessFlag);
58 if (name == null) {
59 continue;
60 }
61 String version = getRegistryValueOrUnknown(rootKey, fullPath, "DisplayVersion", accessFlag);
62 String publisher = getRegistryValueOrUnknown(rootKey, fullPath, "Publisher", accessFlag);
63 String installDate = getRegistryValueOrUnknown(rootKey, fullPath, "InstallDate",
64 accessFlag);
65 String installLocation = getRegistryValueOrUnknown(rootKey, fullPath, "InstallLocation",
66 accessFlag);
67 String installSource = getRegistryValueOrUnknown(rootKey, fullPath, "InstallSource",
68 accessFlag);
69
70 long installDateEpoch = ParseUtil.parseDateToEpoch(installDate, "yyyyMMdd");
71
72 Map<String, String> additionalInfo = new LinkedHashMap<>();
73 additionalInfo.put("installLocation", installLocation);
74 additionalInfo.put("installSource", installSource);
75
76 ApplicationInfo app = new ApplicationInfo(name, version, publisher, installDateEpoch,
77 additionalInfo);
78 appInfoSet.add(app);
79 } catch (Win32Exception e) {
80
81 }
82 }
83 }
84 }
85 }
86
87 return new ArrayList<>(appInfoSet);
88 }
89
90 private static String getRegistryValueOrUnknown(WinReg.HKEY rootKey, String path, String key, int accessFlag) {
91 try {
92 String value = Advapi32Util.registryGetStringValue(rootKey, path, key, accessFlag);
93 if (value != null && !value.trim().isEmpty()) {
94 return value;
95 }
96 } catch (Win32Exception e) {
97 LOG.trace("Unable to access " + path + " with flag " + accessFlag + ": " + e.getMessage());
98 }
99 return null;
100 }
101 }