aboutsummaryrefslogtreecommitdiff
path: root/src/tools/Dtf/Inventory/Features.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/Dtf/Inventory/Features.cs')
-rw-r--r--src/tools/Dtf/Inventory/Features.cs107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/tools/Dtf/Inventory/Features.cs b/src/tools/Dtf/Inventory/Features.cs
new file mode 100644
index 00000000..9d2747ba
--- /dev/null
+++ b/src/tools/Dtf/Inventory/Features.cs
@@ -0,0 +1,107 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3using System;
4using System.IO;
5using System.Data;
6using System.Collections;
7using System.Collections.Generic;
8using System.Globalization;
9using System.Windows.Forms;
10using WixToolset.Dtf.WindowsInstaller;
11
12namespace WixToolset.Dtf.Tools.Inventory
13{
14 /// <summary>
15 /// Provides inventory data about features of products installed on the system.
16 /// </summary>
17 public class FeaturesInventory : IInventoryDataProvider
18 {
19 private static object syncRoot = new object();
20
21 public FeaturesInventory()
22 {
23 }
24
25 public string Description
26 {
27 get { return "Features of installed products"; }
28 }
29
30 public string[] GetNodes(InventoryDataLoadStatusCallback statusCallback)
31 {
32 statusCallback(0, @"Products\...\Features");
33 ArrayList nodes = new ArrayList();
34 foreach (ProductInstallation product in ProductInstallation.AllProducts)
35 {
36 nodes.Add(String.Format(@"Products\{0}\Features", MsiUtils.GetProductName(product.ProductCode)));
37 }
38 statusCallback(nodes.Count, String.Empty);
39 return (string[]) nodes.ToArray(typeof(string));
40 }
41
42 public bool IsNodeSearchable(string searchRoot, string searchNode)
43 {
44 return true;
45 }
46
47 public DataView GetData(string nodePath)
48 {
49 string[] path = nodePath.Split('\\');
50
51 if(path.Length == 3 && path[0] == "Products" && path[2] == "Features")
52 {
53 return GetProductFeaturesData(MsiUtils.GetProductCode(path[1]));
54 }
55 return null;
56 }
57
58 public DataView GetProductFeaturesData(string productCode)
59 {
60 DataTable table = new DataTable("ProductFeatures");
61 table.Locale = CultureInfo.InvariantCulture;
62 table.Columns.Add("ProductFeaturesFeatureTitle", typeof(string));
63 table.Columns.Add("ProductFeaturesFeatureName", typeof(string));
64 table.Columns.Add("ProductFeaturesInstallState", typeof(string));
65
66 try
67 {
68 IntPtr hWnd = IntPtr.Zero;
69 Installer.SetInternalUI(InstallUIOptions.Silent, ref hWnd);
70 lock(syncRoot) // Only one Installer session can be active at a time
71 {
72 using(Session session = Installer.OpenProduct(productCode))
73 {
74 session.DoAction("CostInitialize");
75 session.DoAction("FileCost");
76 session.DoAction("CostFinalize");
77
78 IList<string> featuresAndTitles = session.Database.ExecuteStringQuery(
79 "SELECT `Title`, `Feature` FROM `Feature`");
80
81 for(int i = 0; i < featuresAndTitles.Count; i += 2)
82 {
83 InstallState featureState = session.Features[featuresAndTitles[i + 1]].CurrentState;
84 table.Rows.Add(new object[] { featuresAndTitles[i], featuresAndTitles[i+1],
85 (featureState == InstallState.Advertised ? "Advertised" : featureState.ToString()) });
86 }
87 }
88 }
89 return new DataView(table, "", "ProductFeaturesFeatureTitle ASC", DataViewRowState.CurrentRows);
90 }
91 catch(InstallerException) { }
92 catch(IOException) { }
93 return null;
94 }
95
96 public string GetLink(string nodePath, DataRow row)
97 {
98 string[] path = nodePath.Split('\\');
99
100 if(path.Length == 3 && path[0] == "Products" && path[2] == "Features")
101 {
102 return String.Format(@"Products\{0}\Features\{1}", path[1], row["ProductFeaturesFeatureName"]);
103 }
104 return null;
105 }
106 }
107}