diff options
author | Rob Mensching <rob@firegiant.com> | 2024-03-06 14:48:10 -0800 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2024-03-07 10:55:57 -0800 |
commit | 3d2d46f62fc01e2653d0251ad9703090574e7c41 (patch) | |
tree | ffdf7dce6c646f38b5e3ad8325c2ce78ca891a1a /src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs | |
parent | a8504dc4eb1c2d09965b0858699ac737336ef3c1 (diff) | |
download | wix-3d2d46f62fc01e2653d0251ad9703090574e7c41.tar.gz wix-3d2d46f62fc01e2653d0251ad9703090574e7c41.tar.bz2 wix-3d2d46f62fc01e2653d0251ad9703090574e7c41.zip |
Better .nupkg names
Diffstat (limited to 'src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs')
-rw-r--r-- | src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs b/src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs new file mode 100644 index 00000000..612e8ce9 --- /dev/null +++ b/src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs | |||
@@ -0,0 +1,239 @@ | |||
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.BootstrapperApplicationApi | ||
4 | { | ||
5 | using System; | ||
6 | using System.CodeDom.Compiler; | ||
7 | using System.Collections.Generic; | ||
8 | using System.ComponentModel; | ||
9 | using System.Runtime.InteropServices; | ||
10 | |||
11 | /// <summary> | ||
12 | /// Command-line provided to the bootstrapper application. | ||
13 | /// </summary> | ||
14 | [Serializable] | ||
15 | [StructLayout(LayoutKind.Sequential)] | ||
16 | [GeneratedCodeAttribute("WixToolset.Bootstrapper.InteropCodeGenerator", "1.0.0.0")] | ||
17 | public struct Command | ||
18 | { | ||
19 | // Strings must be declared as pointers so that Marshaling doesn't free them. | ||
20 | [MarshalAs(UnmanagedType.I4)] internal int cbSize; | ||
21 | [MarshalAs(UnmanagedType.U4)] private readonly LaunchAction action; | ||
22 | [MarshalAs(UnmanagedType.U4)] private readonly Display display; | ||
23 | private readonly IntPtr wzCommandLine; | ||
24 | [MarshalAs(UnmanagedType.I4)] private readonly int nCmdShow; | ||
25 | [MarshalAs(UnmanagedType.U4)] private readonly ResumeType resume; | ||
26 | private readonly IntPtr hwndSplashScreen; | ||
27 | [MarshalAs(UnmanagedType.I4)] private readonly RelationType relation; | ||
28 | [MarshalAs(UnmanagedType.Bool)] private readonly bool passthrough; | ||
29 | private readonly IntPtr wzLayoutDirectory; | ||
30 | private readonly IntPtr wzBootstrapperWorkingFolder; | ||
31 | private readonly IntPtr wzBootstrapperApplicationDataPath; | ||
32 | |||
33 | /// <summary> | ||
34 | /// Gets the IBootstrapperCommand for this Command. | ||
35 | /// </summary> | ||
36 | /// <returns>IBootstrapperCommand</returns> | ||
37 | public IBootstrapperCommand GetBootstrapperCommand() | ||
38 | { | ||
39 | return new BootstrapperCommand( | ||
40 | this.action, | ||
41 | this.display, | ||
42 | Marshal.PtrToStringUni(this.wzCommandLine), | ||
43 | this.nCmdShow, | ||
44 | this.resume, | ||
45 | this.hwndSplashScreen, | ||
46 | this.relation, | ||
47 | this.passthrough, | ||
48 | Marshal.PtrToStringUni(this.wzLayoutDirectory), | ||
49 | Marshal.PtrToStringUni(this.wzBootstrapperWorkingFolder), | ||
50 | Marshal.PtrToStringUni(this.wzBootstrapperApplicationDataPath)); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /// <summary> | ||
55 | /// Default implementation of <see cref="IBootstrapperCommand"/>. | ||
56 | /// </summary> | ||
57 | public sealed class BootstrapperCommand : IBootstrapperCommand | ||
58 | { | ||
59 | /// <summary> | ||
60 | /// See <see cref="IBootstrapperCommand"/>. | ||
61 | /// </summary> | ||
62 | public BootstrapperCommand( | ||
63 | LaunchAction action, | ||
64 | Display display, | ||
65 | string commandLine, | ||
66 | int cmdShow, | ||
67 | ResumeType resume, | ||
68 | IntPtr splashScreen, | ||
69 | RelationType relation, | ||
70 | bool passthrough, | ||
71 | string layoutDirectory, | ||
72 | string bootstrapperWorkingFolder, | ||
73 | string bootstrapperApplicationDataPath) | ||
74 | { | ||
75 | this.Action = action; | ||
76 | this.Display = display; | ||
77 | this.CommandLine = commandLine; | ||
78 | this.CmdShow = cmdShow; | ||
79 | this.Resume = resume; | ||
80 | this.SplashScreen = splashScreen; | ||
81 | this.Relation = relation; | ||
82 | this.Passthrough = passthrough; | ||
83 | this.LayoutDirectory = layoutDirectory; | ||
84 | this.BootstrapperWorkingFolder = bootstrapperWorkingFolder; | ||
85 | this.BootstrapperApplicationDataPath = bootstrapperApplicationDataPath; | ||
86 | } | ||
87 | |||
88 | /// <inheritdoc/> | ||
89 | public LaunchAction Action { get; } | ||
90 | |||
91 | /// <inheritdoc/> | ||
92 | public Display Display { get; } | ||
93 | |||
94 | /// <inheritdoc/> | ||
95 | public string CommandLine { get; } | ||
96 | |||
97 | /// <inheritdoc/> | ||
98 | public int CmdShow { get; } | ||
99 | |||
100 | /// <inheritdoc/> | ||
101 | public ResumeType Resume { get; } | ||
102 | |||
103 | /// <inheritdoc/> | ||
104 | public IntPtr SplashScreen { get; } | ||
105 | |||
106 | /// <inheritdoc/> | ||
107 | public RelationType Relation { get; } | ||
108 | |||
109 | /// <inheritdoc/> | ||
110 | public bool Passthrough { get; } | ||
111 | |||
112 | /// <inheritdoc/> | ||
113 | public string LayoutDirectory { get; } | ||
114 | |||
115 | /// <inheritdoc/> | ||
116 | public string BootstrapperWorkingFolder { get; } | ||
117 | |||
118 | /// <inheritdoc/> | ||
119 | public string BootstrapperApplicationDataPath { get; } | ||
120 | |||
121 | /// <inheritdoc/> | ||
122 | public IMbaCommand ParseCommandLine() | ||
123 | { | ||
124 | var args = ParseCommandLineToArgs(this.CommandLine); | ||
125 | var unknownArgs = new List<string>(); | ||
126 | var variables = new List<KeyValuePair<string, string>>(); | ||
127 | var restart = Restart.Unknown; | ||
128 | |||
129 | foreach (var arg in args) | ||
130 | { | ||
131 | var unknownArg = false; | ||
132 | |||
133 | if (arg[0] == '-' || arg[0] == '/') | ||
134 | { | ||
135 | var parameter = arg.Substring(1).ToLowerInvariant(); | ||
136 | switch (parameter) | ||
137 | { | ||
138 | case "norestart": | ||
139 | if (restart == Restart.Unknown) | ||
140 | { | ||
141 | restart = Restart.Never; | ||
142 | } | ||
143 | break; | ||
144 | case "forcerestart": | ||
145 | if (restart == Restart.Unknown) | ||
146 | { | ||
147 | restart = Restart.Always; | ||
148 | } | ||
149 | break; | ||
150 | default: | ||
151 | unknownArg = true; | ||
152 | break; | ||
153 | } | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | var index = arg.IndexOf('='); | ||
158 | if (index == -1) | ||
159 | { | ||
160 | unknownArg = true; | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | var name = arg.Substring(0, index); | ||
165 | var value = arg.Substring(index + 1); | ||
166 | variables.Add(new KeyValuePair<string, string>(name, value)); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | if (unknownArg) | ||
171 | { | ||
172 | unknownArgs.Add(arg); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (restart == Restart.Unknown) | ||
177 | { | ||
178 | restart = this.Display < Display.Full ? Restart.Automatic : Restart.Prompt; | ||
179 | } | ||
180 | |||
181 | return new MbaCommand | ||
182 | { | ||
183 | Restart = restart, | ||
184 | UnknownCommandLineArgs = unknownArgs.ToArray(), | ||
185 | Variables = variables.ToArray(), | ||
186 | }; | ||
187 | } | ||
188 | |||
189 | /// <summary> | ||
190 | /// Gets the command line arguments as a string array. | ||
191 | /// </summary> | ||
192 | /// <returns> | ||
193 | /// Array of command line arguments. | ||
194 | /// </returns> | ||
195 | /// <exception type="Win32Exception">The command line could not be parsed into an array.</exception> | ||
196 | /// <remarks> | ||
197 | /// This method uses the same parsing as the operating system which handles quotes and spaces correctly. | ||
198 | /// </remarks> | ||
199 | public static string[] ParseCommandLineToArgs(string commandLine) | ||
200 | { | ||
201 | if (null == commandLine) | ||
202 | { | ||
203 | return new string[0]; | ||
204 | } | ||
205 | |||
206 | // Parse the filtered command line arguments into a native array. | ||
207 | int argc = 0; | ||
208 | |||
209 | // CommandLineToArgvW tries to treat the first argument as the path to the process, | ||
210 | // which fails pretty miserably if your first argument is something like | ||
211 | // FOO="C:\Program Files\My Company". So give it something harmless to play with. | ||
212 | IntPtr argv = NativeMethods.CommandLineToArgvW("ignored " + commandLine, out argc); | ||
213 | |||
214 | if (IntPtr.Zero == argv) | ||
215 | { | ||
216 | // Throw an exception with the last error. | ||
217 | throw new Win32Exception(); | ||
218 | } | ||
219 | |||
220 | // Marshal each native array pointer to a managed string. | ||
221 | try | ||
222 | { | ||
223 | // Skip "ignored" argument/hack. | ||
224 | string[] args = new string[argc - 1]; | ||
225 | for (int i = 1; i < argc; ++i) | ||
226 | { | ||
227 | IntPtr argvi = Marshal.ReadIntPtr(argv, i * IntPtr.Size); | ||
228 | args[i - 1] = Marshal.PtrToStringUni(argvi); | ||
229 | } | ||
230 | |||
231 | return args; | ||
232 | } | ||
233 | finally | ||
234 | { | ||
235 | NativeMethods.LocalFree(argv); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | } | ||