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.
namespace WixToolset.BootstrapperCore
{
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
public sealed class BootstrapperCommand : IBootstrapperCommand
{
private readonly string commandLine;
public BootstrapperCommand(
LaunchAction action,
Display display,
Restart restart,
string commandLine,
int cmdShow,
ResumeType resume,
IntPtr splashScreen,
RelationType relation,
bool passthrough,
string layoutDirectory)
{
this.Action = action;
this.Display = display;
this.Restart = restart;
this.commandLine = commandLine;
this.CmdShow = cmdShow;
this.Resume = resume;
this.SplashScreen = splashScreen;
this.Relation = relation;
this.Passthrough = passthrough;
this.LayoutDirectory = layoutDirectory;
}
public LaunchAction Action { get; }
public Display Display { get; }
public Restart Restart { get; }
public string[] CommandLineArgs => GetCommandLineArgs(this.commandLine);
public int CmdShow { get; }
public ResumeType Resume { get; }
public IntPtr SplashScreen { get; }
public RelationType Relation { get; }
public bool Passthrough { get; }
public string LayoutDirectory { get; }
/// <summary>
/// Gets the command line arguments as a string array.
/// </summary>
/// <returns>
/// Array of command line arguments.
/// </returns>
/// <exception type="Win32Exception">The command line could not be parsed into an array.</exception>
/// <remarks>
/// This method uses the same parsing as the operating system which handles quotes and spaces correctly.
/// </remarks>
public static string[] GetCommandLineArgs(string commandLine)
{
if (null == commandLine)
{
return new string[0];
}
// Parse the filtered command line arguments into a native array.
int argc = 0;
// CommandLineToArgvW tries to treat the first argument as the path to the process,
// which fails pretty miserably if your first argument is something like
// FOO="C:\Program Files\My Company". So give it something harmless to play with.
IntPtr argv = NativeMethods.CommandLineToArgvW("ignored " + commandLine, out argc);
if (IntPtr.Zero == argv)
{
// Throw an exception with the last error.
throw new Win32Exception();
}
// Marshal each native array pointer to a managed string.
try
{
// Skip "ignored" argument/hack.
string[] args = new string[argc - 1];
for (int i = 1; i < argc; ++i)
{
IntPtr argvi = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
args[i - 1] = Marshal.PtrToStringUni(argvi);
}
return args;
}
finally
{
NativeMethods.LocalFree(argv);
}
}
}
}
|