aboutsummaryrefslogtreecommitdiff
path: root/src/tools/Dtf/Inventory/Features.cs
blob: 9d2747ba101d8b373877b258a992246059ceae57 (plain)
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
// 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.

using System;
using System.IO;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Forms;
using WixToolset.Dtf.WindowsInstaller;

namespace WixToolset.Dtf.Tools.Inventory
{
	/// <summary>
	/// Provides inventory data about features of products installed on the system.
	/// </summary>
	public class FeaturesInventory : IInventoryDataProvider
	{
        private static object syncRoot = new object();

		public FeaturesInventory()
		{
		}

		public string Description
		{
			get { return "Features of installed products"; }
		}

		public string[] GetNodes(InventoryDataLoadStatusCallback statusCallback)
		{
            statusCallback(0, @"Products\...\Features");
            ArrayList nodes = new ArrayList();
			foreach (ProductInstallation product in ProductInstallation.AllProducts)
			{
                nodes.Add(String.Format(@"Products\{0}\Features", MsiUtils.GetProductName(product.ProductCode)));
			}
			statusCallback(nodes.Count, String.Empty);
			return (string[]) nodes.ToArray(typeof(string));
		}

		public bool IsNodeSearchable(string searchRoot, string searchNode)
		{
			return true;
		}

		public DataView GetData(string nodePath)
		{
			string[] path = nodePath.Split('\\');

			if(path.Length == 3 && path[0] == "Products" && path[2] == "Features")
			{
				return GetProductFeaturesData(MsiUtils.GetProductCode(path[1]));
			}
			return null;
		}

		public DataView GetProductFeaturesData(string productCode)
		{
			DataTable table = new DataTable("ProductFeatures");
			table.Locale = CultureInfo.InvariantCulture;
			table.Columns.Add("ProductFeaturesFeatureTitle", typeof(string));
			table.Columns.Add("ProductFeaturesFeatureName", typeof(string));
			table.Columns.Add("ProductFeaturesInstallState", typeof(string));

			try
			{
				IntPtr hWnd = IntPtr.Zero;
                Installer.SetInternalUI(InstallUIOptions.Silent, ref hWnd);
				lock(syncRoot)  // Only one Installer session can be active at a time
				{
					using(Session session = Installer.OpenProduct(productCode))
					{
						session.DoAction("CostInitialize");
						session.DoAction("FileCost");
						session.DoAction("CostFinalize");

						IList<string> featuresAndTitles = session.Database.ExecuteStringQuery(
							"SELECT `Title`, `Feature` FROM `Feature`");

						for(int i = 0; i < featuresAndTitles.Count; i += 2)
						{
                            InstallState featureState = session.Features[featuresAndTitles[i + 1]].CurrentState;
							table.Rows.Add(new object[] { featuresAndTitles[i], featuresAndTitles[i+1],
															(featureState == InstallState.Advertised ? "Advertised" : featureState.ToString()) });
						}
					}
				}
				return new DataView(table, "", "ProductFeaturesFeatureTitle ASC", DataViewRowState.CurrentRows);
			}
			catch(InstallerException) { }
			catch(IOException) { }
			return null;
		}

		public string GetLink(string nodePath, DataRow row)
		{
			string[] path = nodePath.Split('\\');

			if(path.Length == 3 && path[0] == "Products" && path[2] == "Features")
			{
				return String.Format(@"Products\{0}\Features\{1}", path[1], row["ProductFeaturesFeatureName"]);
			}
			return null;
		}
	}
}