forked from PowerShell/PowerShell
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgramsProvider.cs
More file actions
230 lines (194 loc) · 11.3 KB
/
Copy pathProgramsProvider.cs
File metadata and controls
230 lines (194 loc) · 11.3 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
namespace Microsoft.PackageManagement.Providers.Internal {
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management.Automation;
using System.Security.AccessControl;
using PackageManagement.Internal;
using PackageManagement.Internal.Implementation;
using PackageManagement.Internal.Packaging;
using PackageManagement.Internal.Utility.Platform;
using PackageManagement.Internal.Utility.Extensions;
using Win32;
using File = System.IO.File;
public class ProgramsProvider {
/// <summary>
/// The name of this Package Provider
/// </summary>
internal const string ProviderName = "Programs";
private static readonly Dictionary<string, string[]> _features = new Dictionary<string, string[]>();
/// <summary>
/// Returns the name of the Provider.
/// </summary>
/// <returns>The name of this provider (uses the constant declared at the top of the class)</returns>
public string GetPackageProviderName() {
return ProviderName;
}
/// <summary>
/// Performs one-time initialization of the PROVIDER.
/// </summary>
/// <param name="request">
/// An object passed in from the CORE that contains functions that can be used to interact with
/// the CORE and HOST
/// </param>
public void InitializeProvider(Request request) {
if (request == null) {
throw new ArgumentNullException("request");
}
// Nice-to-have put a debug message in that tells what's going on.
request.Debug("Calling '{0}::InitializeProvider'", ProviderName);
}
/// <summary>
/// Returns a collection of strings to the client advertizing features this provider supports.
/// </summary>
/// <param name="request">
/// An object passed in from the CORE that contains functions that can be used to interact with
/// the CORE and HOST
/// </param>
public void GetFeatures(Request request) {
if (request == null) {
throw new ArgumentNullException("request");
}
// Nice-to-have put a debug message in that tells what's going on.
request.Debug("Calling '{0}::GetFeatures' ", ProviderName);
foreach (var feature in _features) {
request.Yield(feature);
}
}
/// <summary>
/// Returns dynamic option definitions to the HOST
/// </summary>
/// <param name="category">The category of dynamic options that the HOST is interested in</param>
/// <param name="request">
/// An object passed in from the CORE that contains functions that can be used to interact with
/// the CORE and HOST
/// </param>
public void GetDynamicOptions(string category, Request request) {
if (request == null) {
throw new ArgumentNullException("request");
}
category = category ?? string.Empty;
// Nice-to-have put a debug message in that tells what's going on.
request.Debug("Calling '{0}::GetDynamicOptions' '{1}'", ProviderName, category);
switch (category.ToLowerInvariant()) {
case "install":
// options required for install/uninstall/getinstalledpackages
request.YieldDynamicOption("IncludeWindowsInstaller", "Switch", false);
request.YieldDynamicOption("IncludeSystemComponent", "Switch", false);
break;
case "provider":
// options used with this provider. Not currently used.
break;
case "source":
// options for package sources
break;
case "package":
// options used when searching for packages
break;
}
}
/// <summary>
/// Returns the packages that are installed
/// </summary>
/// <param name="name">the package name to match. Empty or null means match everything</param>
/// <param name="requiredVersion">the specific version asked for. If this parameter is specified (ie, not null or empty string) then the minimum and maximum values are ignored</param>
/// <param name="minimumVersion">the minimum version of packages to return . If the <code>requiredVersion</code> parameter is specified (ie, not null or empty string) this should be ignored</param>
/// <param name="maximumVersion">the maximum version of packages to return . If the <code>requiredVersion</code> parameter is specified (ie, not null or empty string) this should be ignored</param>
/// <param name="request">
/// An object passed in from the CORE that contains functions that can be used to interact with
/// the CORE and HOST
/// </param>
public void GetInstalledPackages(string name, string requiredVersion, string minimumVersion, string maximumVersion, Request request) {
if (request == null) {
throw new ArgumentNullException("request");
}
// Nice-to-have put a debug message in that tells what's going on.
request.Debug("Calling '{0}::GetInstalledPackages' '{1}','{2}','{3}','{4}'", ProviderName, name, requiredVersion, minimumVersion, maximumVersion);
// dump out results.
if (Environment.Is64BitOperatingSystem) {
using (var hklm64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", RegistryKeyPermissionCheck.ReadSubTree, RegistryRights.ReadKey)) {
if (!YieldPackages("hklm64", hklm64, name, requiredVersion, minimumVersion, maximumVersion, request)) {
return;
}
}
using (var hkcu64 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) {
if (!YieldPackages("hkcu64", hkcu64, name, requiredVersion, minimumVersion, maximumVersion, request)) {
return;
}
}
}
using (var hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) {
if (!YieldPackages("hklm32", hklm32, name, requiredVersion, minimumVersion, maximumVersion, request)) {
return;
}
}
using (var hkcu32 = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", false)) {
if (!YieldPackages("hkcu32", hkcu32, name, requiredVersion, minimumVersion, maximumVersion, request)) {
}
}
}
private bool YieldPackages(string hive, RegistryKey regkey, string name, string requiredVersion, string minimumVersion, string maximumVersion, Request request) {
if (regkey != null) {
var includeWindowsInstaller = request.GetOptionValue("IncludeWindowsInstaller").IsTrue();
var includeSystemComponent = request.GetOptionValue("IncludeSystemComponent").IsTrue();
var wildcardPattern = new WildcardPattern(name??"", WildcardOptions.CultureInvariant | WildcardOptions.IgnoreCase);
foreach (var key in regkey.GetSubKeyNames()) {
var subkey = regkey.OpenSubKey(key);
if (subkey != null) {
var properties = subkey.GetValueNames().ToDictionaryNicely(each => each.ToString(), each => (subkey.GetValue(each) ?? string.Empty).ToString(), StringComparer.OrdinalIgnoreCase);
if (!includeWindowsInstaller && properties.ContainsKey("WindowsInstaller") && properties["WindowsInstaller"] == "1") {
continue;
}
if (!includeSystemComponent && properties.ContainsKey("SystemComponent") && properties["SystemComponent"] == "1") {
continue;
}
var productName = "";
if (!properties.TryGetValue("DisplayName", out productName)) {
// no product name?
continue;
}
if (!string.IsNullOrWhiteSpace(productName) && (string.IsNullOrWhiteSpace(name) || wildcardPattern.IsMatch(productName))) {
var productVersion = properties.Get("DisplayVersion") ?? "";
var publisher = properties.Get("Publisher") ?? "";
var uninstallString = properties.Get("QuietUninstallString") ?? properties.Get("UninstallString") ?? "";
var comments = properties.Get("Comments") ?? "";
var fp = hive + @"\" + subkey;
if (!string.IsNullOrEmpty(requiredVersion)) {
if (SoftwareIdentityVersionComparer.CompareVersions("unknown", requiredVersion, productVersion) != 0) {
continue;
}
} else {
if (!string.IsNullOrEmpty(minimumVersion) && SoftwareIdentityVersionComparer.CompareVersions("unknown", productVersion, minimumVersion) < 0) {
continue;
}
if (!string.IsNullOrEmpty(maximumVersion) && SoftwareIdentityVersionComparer.CompareVersions("unknown", productVersion, maximumVersion) > 0) {
continue;
}
}
if (request.YieldSoftwareIdentity(fp, productName, productVersion, "unknown", comments, "", name, "", "") != null) {
if (properties.Keys.Where(each => !string.IsNullOrWhiteSpace(each)).Any(k => request.AddMetadata(fp, k.MakeSafeFileName(), properties[k]) == null)) {
return false;
}
}
}
}
}
}
return true;
}
}
}