main
cs 235 lines 7.87 KB
Raw
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
3 namespace WixToolset.WixBA
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.IO;
9 using System.Net;
10 using System.Text;
11 using WixToolset.BootstrapperApplicationApi;
12
13 using Threading = System.Windows.Threading;
14 using WinForms = System.Windows.Forms;
15
16 /// <summary>
17 /// The WiX toolset bootstrapper application.
18 /// </summary>
19 public class WixBA : BootstrapperApplication
20 {
21 internal IBootstrapperApplicationData BAManifest { get; private set; }
22
23 internal IBootstrapperCommand Command { get; private set; }
24
25 internal IEngine Engine => this.engine;
26
27 /// <summary>
28 /// Gets the global model.
29 /// </summary>
30 static public Model Model { get; private set; }
31
32 /// <summary>
33 /// Gets the global view.
34 /// </summary>
35 static public RootView View { get; private set; }
36 // TODO: We should refactor things so we dont have a global View.
37
38 /// <summary>
39 /// Gets the global dispatcher.
40 /// </summary>
41 static public Threading.Dispatcher Dispatcher { get; private set; }
42
43 /// <summary>
44 /// Launches the default web browser to the provided URI.
45 /// </summary>
46 /// <param name="uri">URI to open the web browser.</param>
47 public static void LaunchUrl(string uri)
48 {
49 WixBA.UseShellExecute(uri);
50 }
51
52 /// <summary>
53 /// Open a log file.
54 /// </summary>
55 /// <param name="uri">URI to a log file.</param>
56 internal static void OpenLog(Uri uri)
57 {
58 WixBA.UseShellExecute(uri.ToString());
59 }
60
61 /// <summary>
62 /// Open a log folder.
63 /// </summary>
64 /// <param name="string">path to a log folder.</param>
65 internal static void OpenLogFolder(string logFolder)
66 {
67 WixBA.UseShellExecute(logFolder);
68 }
69
70 /// <summary>
71 /// Open a log folder.
72 /// </summary>
73 /// <param name="uri">path to a log folder.</param>
74 private static void UseShellExecute(string path)
75 {
76 // Switch the wait cursor since shellexec can take a second or so.
77 System.Windows.Input.Cursor cursor = WixBA.View.Cursor;
78 WixBA.View.Cursor = System.Windows.Input.Cursors.Wait;
79 Process process = null;
80 try
81 {
82 process = new Process();
83 process.StartInfo.FileName = path;
84 process.StartInfo.UseShellExecute = true;
85 process.StartInfo.Verb = "open";
86
87 process.Start();
88 }
89 finally
90 {
91 if (null != process)
92 {
93 process.Dispose();
94 }
95 // back to the original cursor.
96 WixBA.View.Cursor = cursor;
97 }
98 }
99
100 /// <summary>
101 /// Starts planning the appropriate action.
102 /// </summary>
103 /// <param name="action">Action to plan.</param>
104 public static void Plan(LaunchAction action)
105 {
106 WixBA.Model.PlannedAction = action;
107 WixBA.Model.Engine.Plan(WixBA.Model.PlannedAction);
108 }
109
110 public static void PlanLayout()
111 {
112 // Either default or set the layout directory
113 if (String.IsNullOrEmpty(WixBA.Model.Command.LayoutDirectory))
114 {
115 WixBA.Model.LayoutDirectory = Directory.GetCurrentDirectory();
116
117 // Ask the user for layout folder if one wasn't provided and we're in full UI mode
118 if (WixBA.Model.Command.Display == Display.Full)
119 {
120 WixBA.Dispatcher.Invoke((Action)delegate()
121 {
122 WinForms.FolderBrowserDialog browserDialog = new WinForms.FolderBrowserDialog();
123 browserDialog.RootFolder = Environment.SpecialFolder.MyComputer;
124
125 // Default to the current directory.
126 browserDialog.SelectedPath = WixBA.Model.LayoutDirectory;
127 WinForms.DialogResult result = browserDialog.ShowDialog();
128
129 if (WinForms.DialogResult.OK == result)
130 {
131 WixBA.Model.LayoutDirectory = browserDialog.SelectedPath;
132 WixBA.Plan(WixBA.Model.Command.Action);
133 }
134 else
135 {
136 WixBA.View.Close();
137 }
138 }
139 );
140 }
141 }
142 else
143 {
144 WixBA.Model.LayoutDirectory = WixBA.Model.Command.LayoutDirectory;
145 WixBA.Plan(WixBA.Model.Command.Action);
146 }
147 }
148
149 /// <summary>
150 /// Thread entry point for WiX Toolset Bootstrapper Application.
151 /// </summary>
152 protected override void Run()
153 {
154 this.Engine.Log(LogLevel.Verbose, "Running the WiX BA.");
155 WixBA.Model = new Model(this);
156 WixBA.Dispatcher = Threading.Dispatcher.CurrentDispatcher;
157 RootViewModel viewModel = new RootViewModel();
158 WixBA.View = new RootView(viewModel);
159
160 // Create a Window to show UI.
161 if (WixBA.Model.Command.Display == Display.Passive ||
162 WixBA.Model.Command.Display == Display.Full)
163 {
164 this.Engine.Log(LogLevel.Verbose, "Creating a UI.");
165 WixBA.View.Show();
166 }
167
168 // Kick off detect which will populate the view models.
169 this.Engine.Detect();
170
171 Threading.Dispatcher.Run();
172
173 this.PostTelemetry();
174
175 var exitCode = WixBA.Model.Result;
176 if ((exitCode & 0xFFFF0000) == unchecked(0x80070000))
177 {
178 exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT.
179 }
180
181 this.Engine.Quit(exitCode);
182 }
183
184 protected override void OnCreate(CreateEventArgs args)
185 {
186 base.OnCreate(args);
187 this.Command = args.Command;
188 this.BAManifest = new BootstrapperApplicationData();
189 }
190
191 private void PostTelemetry()
192 {
193 string result = String.Concat("0x", WixBA.Model.Result.ToString("x"));
194
195 StringBuilder telemetryData = new StringBuilder();
196 foreach (KeyValuePair<string, string> kvp in WixBA.Model.Telemetry)
197 {
198 telemetryData.AppendFormat("{0}={1}+", kvp.Key, kvp.Value);
199 }
200 telemetryData.AppendFormat("Result={0}", result);
201
202 byte[] data = Encoding.UTF8.GetBytes(telemetryData.ToString());
203
204 try
205 {
206 HttpWebRequest post = WixBA.Model.CreateWebRequest(String.Format(WixDistribution.TelemetryUrlFormat, WixBA.Model.Version.ToString(), result));
207 post.Method = "POST";
208 post.ContentType = "application/x-www-form-urlencoded";
209 post.ContentLength = data.Length;
210
211 using (Stream postStream = post.GetRequestStream())
212 {
213 postStream.Write(data, 0, data.Length);
214 }
215
216 HttpWebResponse response = (HttpWebResponse)post.GetResponse();
217 }
218 catch (ArgumentException)
219 {
220 }
221 catch (FormatException)
222 {
223 }
224 catch (OverflowException)
225 {
226 }
227 catch (ProtocolViolationException)
228 {
229 }
230 catch (WebException)
231 {
232 }
233 }
234 }
235 }