aboutsummaryrefslogtreecommitdiff
path: root/src/samples
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-04-22 17:06:54 -0700
committerRob Mensching <rob@firegiant.com>2021-04-29 16:36:06 -0700
commitaf10c45d7b3a44af0b461a557847fe03263dcc10 (patch)
tree6a5c1532304782c36ffe4200b38f3afb76789a43 /src/samples
parent9c2aed97299fb96aeee3f1471ce40225437aaecf (diff)
downloadwix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.gz
wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.bz2
wix-af10c45d7b3a44af0b461a557847fe03263dcc10.zip
Move burn into burn
Diffstat (limited to 'src/samples')
-rw-r--r--src/samples/burn/ManagedBundleRunner/BundleErrorEventArgs.cs33
-rw-r--r--src/samples/burn/ManagedBundleRunner/BundleProgressEventArgs.cs23
-rw-r--r--src/samples/burn/ManagedBundleRunner/BundleResult.cs24
-rw-r--r--src/samples/burn/ManagedBundleRunner/BundleRunner.cs212
-rw-r--r--src/samples/burn/runbundle/AssemblyInfo.cs12
-rw-r--r--src/samples/burn/runbundle/Program.cs47
6 files changed, 351 insertions, 0 deletions
diff --git a/src/samples/burn/ManagedBundleRunner/BundleErrorEventArgs.cs b/src/samples/burn/ManagedBundleRunner/BundleErrorEventArgs.cs
new file mode 100644
index 00000000..2c377326
--- /dev/null
+++ b/src/samples/burn/ManagedBundleRunner/BundleErrorEventArgs.cs
@@ -0,0 +1,33 @@
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 Wix.Samples
4{
5 using System;
6
7 /// <summary>
8 /// Arguments provided when bundle encounters an error.
9 /// </summary>
10 [Serializable]
11 public class BundleErrorEventArgs : EventArgs
12 {
13 /// <summary>
14 /// Gets the error code.
15 /// </summary>
16 public int Code { get; set; }
17
18 /// <summary>
19 /// Gets the error message.
20 /// </summary>
21 public string Message { get; set; }
22
23 /// <summary>
24 /// Gets the recommended display flags for an error dialog.
25 /// </summary>
26 public int UIHint { get; set; }
27
28 /// <summary>
29 /// Gets or sets the <see cref="Result"/> of the operation. This is passed back to the bundle.
30 /// </summary>
31 public BundleResult Result { get; set; }
32 }
33}
diff --git a/src/samples/burn/ManagedBundleRunner/BundleProgressEventArgs.cs b/src/samples/burn/ManagedBundleRunner/BundleProgressEventArgs.cs
new file mode 100644
index 00000000..ed42b5b1
--- /dev/null
+++ b/src/samples/burn/ManagedBundleRunner/BundleProgressEventArgs.cs
@@ -0,0 +1,23 @@
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 Wix.Samples
4{
5 using System;
6
7 /// <summary>
8 /// Arguments provided when bundle progress is updated.
9 /// </summary>
10 [Serializable]
11 public class BundleProgressEventArgs : EventArgs
12 {
13 /// <summary>
14 /// Gets the percentage from 0 to 100 completed for a bundle.
15 /// </summary>
16 public int Progress { get; set; }
17
18 /// <summary>
19 /// Gets or sets the <see cref="Result"/> of the operation. This is passed back to the bundle.
20 /// </summary>
21 public BundleResult Result { get; set; }
22 }
23}
diff --git a/src/samples/burn/ManagedBundleRunner/BundleResult.cs b/src/samples/burn/ManagedBundleRunner/BundleResult.cs
new file mode 100644
index 00000000..c32644f4
--- /dev/null
+++ b/src/samples/burn/ManagedBundleRunner/BundleResult.cs
@@ -0,0 +1,24 @@
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 Wix.Samples
4{
5 /// <summary>
6 /// Result codes.
7 /// </summary>
8 public enum BundleResult
9 {
10 Error = -1,
11 None,
12 Ok,
13 Cancel,
14 Abort,
15 Retry,
16 Ignore,
17 Yes,
18 No,
19 Close,
20 Help,
21 TryAgain,
22 Continue,
23 }
24}
diff --git a/src/samples/burn/ManagedBundleRunner/BundleRunner.cs b/src/samples/burn/ManagedBundleRunner/BundleRunner.cs
new file mode 100644
index 00000000..e2089787
--- /dev/null
+++ b/src/samples/burn/ManagedBundleRunner/BundleRunner.cs
@@ -0,0 +1,212 @@
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 Wix.Samples
4{
5 using System;
6 using System.Diagnostics;
7 using System.IO.Pipes;
8 using System.Text;
9 using System.Threading;
10
11 /// <summary>
12 /// Runs a bundle with provided command-line.
13 /// </summary>
14 public class BundleRunner
15 {
16 /// <summary>
17 /// Creates a runner for the provided bundle.
18 /// </summary>
19 /// <param name="bundle">Path to the bundle to run.</param>
20 public BundleRunner(string bundle)
21 {
22 this.Path = bundle;
23 }
24
25 /// <summary>
26 /// Fired when the bundle encounters an error.
27 /// </summary>
28 public event EventHandler<BundleErrorEventArgs> Error;
29
30 /// <summary>
31 /// Fired when the bundle progress is udpated.
32 /// </summary>
33 public event EventHandler<BundleProgressEventArgs> Progress;
34
35 /// <summary>
36 /// Gets the path to the bundle to run.
37 /// </summary>
38 public string Path { get; private set; }
39
40 /// <summary>
41 /// Runs the bundle with the provided command-line.
42 /// </summary>
43 /// <param name="commandLine">Optional command-line to pass to the bundle.</param>
44 /// <returns>Exit code from the bundle.</returns>
45 public int Run(string commandLine = null)
46 {
47 WaitHandle[] waits = new WaitHandle[] { new ManualResetEvent(false), new ManualResetEvent(false) };
48 int returnCode = 0;
49 int pid = Process.GetCurrentProcess().Id;
50 string pipeName = String.Concat("bpe_", pid);
51 string pipeSecret = Guid.NewGuid().ToString("N");
52
53 using (NamedPipeServerStream pipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1))
54 {
55 using (Process bundleProcess = new Process())
56 {
57 bundleProcess.StartInfo.FileName = this.Path;
58 bundleProcess.StartInfo.Arguments = String.Format("{0} -burn.embedded {1} {2} {3}", commandLine ?? String.Empty, pipeName, pipeSecret, pid);
59 bundleProcess.StartInfo.UseShellExecute = false;
60 bundleProcess.StartInfo.CreateNoWindow = true;
61 bundleProcess.Start();
62
63 Connect(pipe, pipeSecret, pid, bundleProcess.Id);
64
65 PumpMessages(pipe);
66
67 bundleProcess.WaitForExit();
68 returnCode = bundleProcess.ExitCode;
69 }
70 }
71
72 return returnCode;
73 }
74
75 /// <summary>
76 /// Called when bundle encounters an error.
77 /// </summary>
78 /// <param name="e">Additional arguments for this event.</param>
79 protected virtual void OnError(BundleErrorEventArgs e)
80 {
81 EventHandler<BundleErrorEventArgs> handler = this.Error;
82 if (handler != null)
83 {
84 handler(this, e);
85 }
86 }
87
88 /// <summary>
89 /// Called when bundle progress is updated.
90 /// </summary>
91 /// <param name="e">Additional arguments for this event.</param>
92 protected virtual void OnProgress(BundleProgressEventArgs e)
93 {
94 EventHandler<BundleProgressEventArgs> handler = this.Progress;
95 if (handler != null)
96 {
97 handler(this, e);
98 }
99 }
100
101 private void Connect(NamedPipeServerStream pipe, string pipeSecret, int pid, int childPid)
102 {
103 pipe.WaitForConnection();
104
105 WriteSecretToPipe(pipe, pipeSecret);
106
107 WriteNumberToPipe(pipe, (uint)pid);
108
109 uint ack = ReadNumberFromPipe(pipe);
110 // This is not true when bundle is run under a debugger
111 //if (ack != childPid)
112 //{
113 // throw new ApplicationException("Incorrect child process.");
114 //}
115 }
116
117 private void PumpMessages(NamedPipeServerStream pipe)
118 {
119 uint messageId;
120 while (TryReadNumberFromPipe(pipe, out messageId))
121 {
122 uint messageSize = ReadNumberFromPipe(pipe);
123
124 BundleResult result = BundleResult.None;
125 switch (messageId)
126 {
127 case 1: //error
128 result = ProcessErrorMessage(pipe);
129 break;
130
131 case 2: // progress
132 result = ProcessProgressMessage(pipe);
133 break;
134
135 default: // unknown message, do nothing.
136 break;
137 }
138
139 CompleteMessage(pipe, result);
140 }
141 }
142
143 private BundleResult ProcessErrorMessage(NamedPipeServerStream pipe)
144 {
145 BundleErrorEventArgs e = new BundleErrorEventArgs();
146 e.Code = (int)ReadNumberFromPipe(pipe);
147 e.Message = ReadStringFromPipe(pipe);
148 e.UIHint = (int)ReadNumberFromPipe(pipe);
149
150 this.OnError(e);
151
152 return e.Result;
153 }
154
155 private BundleResult ProcessProgressMessage(NamedPipeServerStream pipe)
156 {
157 ReadNumberFromPipe(pipe); // eat the first progress number because it is always zero.
158
159 BundleProgressEventArgs e = new BundleProgressEventArgs();
160 e.Progress = (int)ReadNumberFromPipe(pipe);
161
162 this.OnProgress(e);
163
164 return e.Result;
165 }
166
167 private void CompleteMessage(NamedPipeServerStream pipe, BundleResult result)
168 {
169 uint complete = 0xF0000002;
170 WriteNumberToPipe(pipe, complete);
171 WriteNumberToPipe(pipe, 4); // size of message data
172 WriteNumberToPipe(pipe, (uint)result);
173 }
174
175 private uint ReadNumberFromPipe(NamedPipeServerStream pipe)
176 {
177 byte[] buffer = new byte[4];
178 pipe.Read(buffer, 0, buffer.Length);
179 return BitConverter.ToUInt32(buffer, 0);
180 }
181
182 private string ReadStringFromPipe(NamedPipeServerStream pipe)
183 {
184 uint length = ReadNumberFromPipe(pipe);
185
186 byte[] buffer = new byte[length * 2];
187 pipe.Read(buffer, 0, buffer.Length);
188
189 return Encoding.Unicode.GetString(buffer);
190 }
191
192 private bool TryReadNumberFromPipe(NamedPipeServerStream pipe, out uint value)
193 {
194 value = ReadNumberFromPipe(pipe); // reading will not block and return zero if pipe is not connected.
195 return pipe.IsConnected;
196 }
197
198 private void WriteNumberToPipe(NamedPipeServerStream pipe, uint value)
199 {
200 byte[] buffer = BitConverter.GetBytes(value);
201 pipe.Write(buffer, 0, buffer.Length);
202 }
203
204 private void WriteSecretToPipe(NamedPipeServerStream pipe, string secret)
205 {
206 byte[] buffer = Encoding.Unicode.GetBytes(secret);
207
208 WriteNumberToPipe(pipe, (uint)buffer.Length);
209 pipe.Write(buffer, 0, buffer.Length);
210 }
211 }
212}
diff --git a/src/samples/burn/runbundle/AssemblyInfo.cs b/src/samples/burn/runbundle/AssemblyInfo.cs
new file mode 100644
index 00000000..3a66d5e3
--- /dev/null
+++ b/src/samples/burn/runbundle/AssemblyInfo.cs
@@ -0,0 +1,12 @@
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.Reflection;
5using System.Runtime.CompilerServices;
6using System.Runtime.InteropServices;
7
8[assembly: AssemblyTitle("Executable to demonstrate Bundle Runner Sample")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyCulture("")]
11[assembly: CLSCompliant(true)]
12[assembly: ComVisible(false)]
diff --git a/src/samples/burn/runbundle/Program.cs b/src/samples/burn/runbundle/Program.cs
new file mode 100644
index 00000000..8edca5dc
--- /dev/null
+++ b/src/samples/burn/runbundle/Program.cs
@@ -0,0 +1,47 @@
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 Wix.Samples
4{
5 using System;
6 using System.Linq;
7 using Wix.Samples;
8
9 /// <summary>
10 /// Example executable that installs then immediately uninstalls a bundle showing progress.
11 /// </summary>
12 class Program
13 {
14 static int Main(string[] args)
15 {
16 if (args.Length == 0)
17 {
18 Console.WriteLine("Must provide the path to the bundle to install then uninstall.");
19 return -1;
20 }
21
22 BundleRunner runner = new BundleRunner(args[0]);
23 runner.Error += Program.OnError;
24 runner.Progress += Program.OnProgress;
25
26 Console.WriteLine("Installing: {0}", runner.Path);
27 int exitCode = runner.Run(String.Join(" ", args.Skip(1).ToArray()));
28 if (0 == exitCode)
29 {
30 Console.WriteLine("\r\nUninstalling: {0}", runner.Path);
31 exitCode = runner.Run("-uninstall");
32 }
33
34 return exitCode;
35 }
36
37 static void OnError(object sender, BundleErrorEventArgs e)
38 {
39 Console.WriteLine("error: {0}, uiHint: {1}, message: {2}", e.Code, e.UIHint, e.Message);
40 }
41
42 static void OnProgress(object sender, BundleProgressEventArgs e)
43 {
44 Console.WriteLine("progresss: {0}%", e.Progress);
45 }
46 }
47}