From 3d2d46f62fc01e2653d0251ad9703090574e7c41 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 6 Mar 2024 14:48:10 -0800 Subject: Better .nupkg names --- .../BootstrapperCommand.cs | 239 +++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs (limited to 'src/api/burn/WixToolset.BootstrapperApplicationApi/BootstrapperCommand.cs') 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 @@ +// 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.BootstrapperApplicationApi +{ + using System; + using System.CodeDom.Compiler; + using System.Collections.Generic; + using System.ComponentModel; + using System.Runtime.InteropServices; + + /// + /// Command-line provided to the bootstrapper application. + /// + [Serializable] + [StructLayout(LayoutKind.Sequential)] + [GeneratedCodeAttribute("WixToolset.Bootstrapper.InteropCodeGenerator", "1.0.0.0")] + public struct Command + { + // Strings must be declared as pointers so that Marshaling doesn't free them. + [MarshalAs(UnmanagedType.I4)] internal int cbSize; + [MarshalAs(UnmanagedType.U4)] private readonly LaunchAction action; + [MarshalAs(UnmanagedType.U4)] private readonly Display display; + private readonly IntPtr wzCommandLine; + [MarshalAs(UnmanagedType.I4)] private readonly int nCmdShow; + [MarshalAs(UnmanagedType.U4)] private readonly ResumeType resume; + private readonly IntPtr hwndSplashScreen; + [MarshalAs(UnmanagedType.I4)] private readonly RelationType relation; + [MarshalAs(UnmanagedType.Bool)] private readonly bool passthrough; + private readonly IntPtr wzLayoutDirectory; + private readonly IntPtr wzBootstrapperWorkingFolder; + private readonly IntPtr wzBootstrapperApplicationDataPath; + + /// + /// Gets the IBootstrapperCommand for this Command. + /// + /// IBootstrapperCommand + public IBootstrapperCommand GetBootstrapperCommand() + { + return new BootstrapperCommand( + this.action, + this.display, + Marshal.PtrToStringUni(this.wzCommandLine), + this.nCmdShow, + this.resume, + this.hwndSplashScreen, + this.relation, + this.passthrough, + Marshal.PtrToStringUni(this.wzLayoutDirectory), + Marshal.PtrToStringUni(this.wzBootstrapperWorkingFolder), + Marshal.PtrToStringUni(this.wzBootstrapperApplicationDataPath)); + } + } + + /// + /// Default implementation of . + /// + public sealed class BootstrapperCommand : IBootstrapperCommand + { + /// + /// See . + /// + public BootstrapperCommand( + LaunchAction action, + Display display, + string commandLine, + int cmdShow, + ResumeType resume, + IntPtr splashScreen, + RelationType relation, + bool passthrough, + string layoutDirectory, + string bootstrapperWorkingFolder, + string bootstrapperApplicationDataPath) + { + this.Action = action; + this.Display = display; + this.CommandLine = commandLine; + this.CmdShow = cmdShow; + this.Resume = resume; + this.SplashScreen = splashScreen; + this.Relation = relation; + this.Passthrough = passthrough; + this.LayoutDirectory = layoutDirectory; + this.BootstrapperWorkingFolder = bootstrapperWorkingFolder; + this.BootstrapperApplicationDataPath = bootstrapperApplicationDataPath; + } + + /// + public LaunchAction Action { get; } + + /// + public Display Display { get; } + + /// + public string CommandLine { get; } + + /// + public int CmdShow { get; } + + /// + public ResumeType Resume { get; } + + /// + public IntPtr SplashScreen { get; } + + /// + public RelationType Relation { get; } + + /// + public bool Passthrough { get; } + + /// + public string LayoutDirectory { get; } + + /// + public string BootstrapperWorkingFolder { get; } + + /// + public string BootstrapperApplicationDataPath { get; } + + /// + public IMbaCommand ParseCommandLine() + { + var args = ParseCommandLineToArgs(this.CommandLine); + var unknownArgs = new List(); + var variables = new List>(); + var restart = Restart.Unknown; + + foreach (var arg in args) + { + var unknownArg = false; + + if (arg[0] == '-' || arg[0] == '/') + { + var parameter = arg.Substring(1).ToLowerInvariant(); + switch (parameter) + { + case "norestart": + if (restart == Restart.Unknown) + { + restart = Restart.Never; + } + break; + case "forcerestart": + if (restart == Restart.Unknown) + { + restart = Restart.Always; + } + break; + default: + unknownArg = true; + break; + } + } + else + { + var index = arg.IndexOf('='); + if (index == -1) + { + unknownArg = true; + } + else + { + var name = arg.Substring(0, index); + var value = arg.Substring(index + 1); + variables.Add(new KeyValuePair(name, value)); + } + } + + if (unknownArg) + { + unknownArgs.Add(arg); + } + } + + if (restart == Restart.Unknown) + { + restart = this.Display < Display.Full ? Restart.Automatic : Restart.Prompt; + } + + return new MbaCommand + { + Restart = restart, + UnknownCommandLineArgs = unknownArgs.ToArray(), + Variables = variables.ToArray(), + }; + } + + /// + /// Gets the command line arguments as a string array. + /// + /// + /// Array of command line arguments. + /// + /// The command line could not be parsed into an array. + /// + /// This method uses the same parsing as the operating system which handles quotes and spaces correctly. + /// + public static string[] ParseCommandLineToArgs(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); + } + } + } +} -- cgit v1.2.3-55-g6feb