-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproduct.go
121 lines (107 loc) · 3.58 KB
/
product.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package wc
import (
"errors"
"golang.org/x/sys/windows/registry"
)
// Product is an installed program
type Product struct {
Bits Bits `firestore:"bits,omitempty"`
Key string `firestore:"key,omitempty"`
DisplayName string `firestore:"displayName,omitempty"`
DisplayVersion string `firestore:"displayVersion,omitempty"`
Publisher string `firestore:"publisher,omitempty"`
Comments string `firestore:"comments,omitempty"`
Contact string `firestore:"contact,omitempty"`
InstallDate string `firestore:"installDate,omitempty"`
InstallSource string `firestore:"installSource,omitempty"`
InstallLocation string `firestore:"installLocation,omitempty"`
ModifyPath string `firestore:"modifyPath,omitempty"`
UninstallString string `firestore:"uninstallString,omitempty"`
URLInfoAbout string `firestore:"urlInfoAbout,omitempty"`
URLUpdateInfo string `firestore:"urlUpdateInfo,omitempty"`
}
// GetProducts fetches products from the registry
func GetProducts() ([]Product, error) {
b32, err := getProducts(BIT32)
if err != nil {
return nil, err
}
b64, err := getProducts(BIT64)
if err != nil {
return nil, err
}
return append(b32, b64...), nil
}
func getProducts(bits Bits) ([]Product, error) {
var productKeyName string
switch bits {
case BIT32:
productKeyName = `SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall`
case BIT64:
productKeyName = `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall`
default:
return nil, errors.New("Bad bits")
}
productsKey, err := registry.OpenKey(registry.LOCAL_MACHINE, productKeyName, registry.ENUMERATE_SUB_KEYS)
if err != nil {
return nil, err
}
defer productsKey.Close()
productKeys, err := productsKey.ReadSubKeyNames(-1)
if err != nil {
return nil, err
}
products := make([]Product, 0)
for _, v := range productKeys {
product, err := func() (Product, error) {
key, err := registry.OpenKey(registry.LOCAL_MACHINE, productKeyName+`\`+v, registry.QUERY_VALUE)
if err != nil {
return Product{}, err
}
defer key.Close()
displayName, _, err := key.GetStringValue("DisplayName")
if err != nil {
return Product{}, err
}
displayVersion, _, _ := key.GetStringValue("DisplayVersion")
publisher, _, _ := key.GetStringValue("Publisher")
comments, _, _ := key.GetStringValue("Comments")
contact, _, _ := key.GetStringValue("Contact")
installDate, _, _ := key.GetStringValue("InstallDate")
installSource, _, _ := key.GetStringValue("InstallSource")
installLocation, _, _ := key.GetStringValue("InstallLocation")
uninstallString, _, _ := key.GetStringValue("UninstallString")
if uninstallString != "" {
uninstallString, _ = registry.ExpandString(uninstallString)
}
modifyPath, _, _ := key.GetStringValue("ModifyPath")
if modifyPath != "" {
modifyPath, _ = registry.ExpandString(modifyPath)
}
urlInfoAbout, _, _ := key.GetStringValue("URLInfoAbout")
urlUpdateInfo, _, _ := key.GetStringValue("URLUpdateInfo")
p := Product{
Bits: bits,
Key: v,
DisplayName: displayName,
DisplayVersion: displayVersion,
Publisher: publisher,
Comments: comments,
Contact: contact,
InstallDate: installDate,
InstallSource: installSource,
InstallLocation: installLocation,
ModifyPath: modifyPath,
UninstallString: uninstallString,
URLInfoAbout: urlInfoAbout,
URLUpdateInfo: urlUpdateInfo,
}
return p, nil
}()
if err != nil {
continue // FIXME?
}
products = append(products, product)
}
return products, nil
}