aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs')
-rw-r--r--src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs
new file mode 100644
index 00000000..af27fd1d
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/ComponentInfo.cs
@@ -0,0 +1,276 @@
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
3namespace WixToolset.Dtf.WindowsInstaller
4{
5 using System;
6 using System.Text;
7 using System.Collections;
8 using System.Collections.Generic;
9
10 /// <summary>
11 /// Accessor for information about components within the context of an installation session.
12 /// </summary>
13 public sealed class ComponentInfoCollection : ICollection<ComponentInfo>
14 {
15 private Session session;
16
17 internal ComponentInfoCollection(Session session)
18 {
19 this.session = session;
20 }
21
22 /// <summary>
23 /// Gets information about a component within the context of an installation session.
24 /// </summary>
25 /// <param name="component">name of the component</param>
26 /// <returns>component object</returns>
27 public ComponentInfo this[string component]
28 {
29 get
30 {
31 return new ComponentInfo(this.session, component);
32 }
33 }
34
35 void ICollection<ComponentInfo>.Add(ComponentInfo item)
36 {
37 throw new InvalidOperationException();
38 }
39
40 void ICollection<ComponentInfo>.Clear()
41 {
42 throw new InvalidOperationException();
43 }
44
45 /// <summary>
46 /// Checks if the collection contains a component.
47 /// </summary>
48 /// <param name="component">name of the component</param>
49 /// <returns>true if the component is in the collection, else false</returns>
50 public bool Contains(string component)
51 {
52 return this.session.Database.CountRows(
53 "Component", "`Component` = '" + component + "'") == 1;
54 }
55
56 bool ICollection<ComponentInfo>.Contains(ComponentInfo item)
57 {
58 return item != null && this.Contains(item.Name);
59 }
60
61 /// <summary>
62 /// Copies the features into an array.
63 /// </summary>
64 /// <param name="array">array that receives the features</param>
65 /// <param name="arrayIndex">offset into the array</param>
66 public void CopyTo(ComponentInfo[] array, int arrayIndex)
67 {
68 foreach (ComponentInfo component in this)
69 {
70 array[arrayIndex++] = component;
71 }
72 }
73
74 /// <summary>
75 /// Gets the number of components defined for the product.
76 /// </summary>
77 public int Count
78 {
79 get
80 {
81 return this.session.Database.CountRows("Component");
82 }
83 }
84
85 bool ICollection<ComponentInfo>.IsReadOnly
86 {
87 get
88 {
89 return true;
90 }
91 }
92
93 bool ICollection<ComponentInfo>.Remove(ComponentInfo item)
94 {
95 throw new InvalidOperationException();
96 }
97
98 /// <summary>
99 /// Enumerates the components in the collection.
100 /// </summary>
101 /// <returns>an enumerator over all features in the collection</returns>
102 public IEnumerator<ComponentInfo> GetEnumerator()
103 {
104 using (View compView = this.session.Database.OpenView(
105 "SELECT `Component` FROM `Component`"))
106 {
107 compView.Execute();
108
109 foreach (Record compRec in compView) using (compRec)
110 {
111 string comp = compRec.GetString(1);
112 yield return new ComponentInfo(this.session, comp);
113 }
114 }
115 }
116
117 IEnumerator IEnumerable.GetEnumerator()
118 {
119 return this.GetEnumerator();
120 }
121 }
122
123 /// <summary>
124 /// Provides access to information about a component within the context of an installation session.
125 /// </summary>
126 public class ComponentInfo
127 {
128 private Session session;
129 private string name;
130
131 internal ComponentInfo(Session session, string name)
132 {
133 this.session = session;
134 this.name = name;
135 }
136
137 /// <summary>
138 /// Gets the name of the component (primary key in the Component table).
139 /// </summary>
140 public string Name
141 {
142 get
143 {
144 return this.name;
145 }
146 }
147
148 /// <summary>
149 /// Gets the current install state of the designated Component.
150 /// </summary>
151 /// <exception cref="InvalidHandleException">the Session handle is invalid</exception>
152 /// <exception cref="ArgumentException">an unknown Component was requested</exception>
153 /// <remarks><p>
154 /// Win32 MSI API:
155 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetcomponentstate.asp">MsiGetComponentState</a>
156 /// </p></remarks>
157 public InstallState CurrentState
158 {
159 get
160 {
161 int installedState, actionState;
162 uint ret = RemotableNativeMethods.MsiGetComponentState((int) this.session.Handle, this.name, out installedState, out actionState);
163 if (ret != 0)
164 {
165 if (ret == (uint) NativeMethods.Error.UNKNOWN_COMPONENT)
166 {
167 throw InstallerException.ExceptionFromReturnCode(ret, this.name);
168 }
169 else
170 {
171 throw InstallerException.ExceptionFromReturnCode(ret);
172 }
173 }
174 return (InstallState) installedState;
175 }
176 }
177
178 /// <summary>
179 /// Gets or sets the action state of the designated Component.
180 /// </summary>
181 /// <exception cref="InvalidHandleException">the Session handle is invalid</exception>
182 /// <exception cref="ArgumentException">an unknown Component was requested</exception>
183 /// <exception cref="InstallCanceledException">the user exited the installation</exception>
184 /// <remarks><p>
185 /// Win32 MSI APIs:
186 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetcomponentstate.asp">MsiGetComponentState</a>,
187 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetcomponentstate.asp">MsiSetComponentState</a>
188 /// </p></remarks>
189 public InstallState RequestState
190 {
191 get
192 {
193 int installedState, actionState;
194 uint ret = RemotableNativeMethods.MsiGetComponentState((int) this.session.Handle, this.name, out installedState, out actionState);
195 if (ret != 0)
196 {
197 if (ret == (uint) NativeMethods.Error.UNKNOWN_COMPONENT)
198 {
199 throw InstallerException.ExceptionFromReturnCode(ret, this.name);
200 }
201 else
202 {
203 throw InstallerException.ExceptionFromReturnCode(ret);
204 }
205 }
206 return (InstallState) actionState;
207 }
208
209 set
210 {
211 uint ret = RemotableNativeMethods.MsiSetComponentState((int) this.session.Handle, this.name, (int) value);
212 if (ret != 0)
213 {
214 if (ret == (uint) NativeMethods.Error.UNKNOWN_COMPONENT)
215 {
216 throw InstallerException.ExceptionFromReturnCode(ret, this.name);
217 }
218 else
219 {
220 throw InstallerException.ExceptionFromReturnCode(ret);
221 }
222 }
223 }
224 }
225
226 /// <summary>
227 /// Gets disk space per drive required to install a component.
228 /// </summary>
229 /// <param name="installState">Requested component state</param>
230 /// <returns>A list of InstallCost structures, specifying the cost for each drive for the component</returns>
231 /// <remarks><p>
232 /// Win32 MSI API:
233 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumcomponentcosts.asp">MsiEnumComponentCosts</a>
234 /// </p></remarks>
235 public IList<InstallCost> GetCost(InstallState installState)
236 {
237 IList<InstallCost> costs = new List<InstallCost>();
238 StringBuilder driveBuf = new StringBuilder(20);
239 for (uint i = 0; true; i++)
240 {
241 int cost, tempCost;
242 uint driveBufSize = (uint) driveBuf.Capacity;
243 uint ret = RemotableNativeMethods.MsiEnumComponentCosts(
244 (int) this.session.Handle,
245 this.name,
246 i,
247 (int) installState,
248 driveBuf,
249 ref driveBufSize,
250 out cost,
251 out tempCost);
252 if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS) break;
253 if (ret == (uint) NativeMethods.Error.MORE_DATA)
254 {
255 driveBuf.Capacity = (int) ++driveBufSize;
256 ret = RemotableNativeMethods.MsiEnumComponentCosts(
257 (int) this.session.Handle,
258 this.name,
259 i,
260 (int) installState,
261 driveBuf,
262 ref driveBufSize,
263 out cost,
264 out tempCost);
265 }
266
267 if (ret != 0)
268 {
269 throw InstallerException.ExceptionFromReturnCode(ret);
270 }
271 costs.Add(new InstallCost(driveBuf.ToString(), cost * 512L, tempCost * 512L));
272 }
273 return costs;
274 }
275 }
276}