diff --git a/src/WinSW.Core/Configuration/YamlConfiguration.cs b/src/WinSW.Core/Configuration/YamlConfiguration.cs index 009c614..d682db6 100644 --- a/src/WinSW.Core/Configuration/YamlConfiguration.cs +++ b/src/WinSW.Core/Configuration/YamlConfiguration.cs @@ -287,7 +287,6 @@ namespace WinSW.Configuration { if (!int.TryParse(this.ZipOlderThanNumDaysYamlLog, out int zipolderthannumdaysValue)) { - // FIXME: Remove the build env specific warning suppression from the codebase throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML."); } diff --git a/src/WinSW.Core/ServiceDescriptor.cs b/src/WinSW.Core/ServiceDescriptor.cs index 109be12..5bd46bd 100644 --- a/src/WinSW.Core/ServiceDescriptor.cs +++ b/src/WinSW.Core/ServiceDescriptor.cs @@ -17,6 +17,7 @@ namespace WinSW public class ServiceDescriptor : IWinSWConfiguration { protected readonly XmlDocument dom = new(); + private readonly Dictionary environmentVariables; public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings(); diff --git a/src/WinSW/Program.cs b/src/WinSW/Program.cs index a9eecad..ceca2b5 100644 --- a/src/WinSW/Program.cs +++ b/src/WinSW/Program.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; +#if VNEXT +using System.IO.Pipes; +#endif #if NET using System.Reflection; #endif @@ -28,6 +31,10 @@ namespace WinSW { public static class Program { +#if VNEXT + private const string NoPipe = "-"; +#endif + private static readonly ILog Log = LogManager.GetLogger(typeof(Program)); public static int Main(string[] args) @@ -127,7 +134,35 @@ namespace WinSW _ = ConsoleApis.FreeConsole(); _ = ConsoleApis.AttachConsole(ConsoleApis.ATTACH_PARENT_PROCESS); +#if VNEXT + string stdinName = args[1]; + if (stdinName != NoPipe) + { + var stdin = new NamedPipeClientStream(".", stdinName, PipeDirection.In, PipeOptions.Asynchronous); + stdin.Connect(); + Console.SetIn(new StreamReader(stdin)); + } + + string stdoutName = args[2]; + if (stdoutName != NoPipe) + { + var stdout = new NamedPipeClientStream(".", stdoutName, PipeDirection.Out, PipeOptions.Asynchronous); + stdout.Connect(); + Console.SetOut(new StreamWriter(stdout) { AutoFlush = true }); + } + + string stderrName = args[3]; + if (stderrName != NoPipe) + { + var stderr = new NamedPipeClientStream(".", stderrName, PipeDirection.Out, PipeOptions.Asynchronous); + stderr.Connect(); + Console.SetError(new StreamWriter(stderr) { AutoFlush = true }); + } + + args = args.GetRange(4, args.Count - 4); +#else args = args.GetRange(1, args.Count - 1); +#endif } else if (Environment.OSVersion.Version.Major == 5) { @@ -565,18 +600,32 @@ namespace WinSW { using var current = Process.GetCurrentProcess(); +#if VNEXT + string? stdinName = Console.IsInputRedirected ? Guid.NewGuid().ToString() : null; + string? stdoutName = Console.IsOutputRedirected ? Guid.NewGuid().ToString() : null; + string? stderrName = Console.IsErrorRedirected ? Guid.NewGuid().ToString() : null; +#endif + + string arguments = "/elevated " + +#if VNEXT + " " + (stdinName ?? NoPipe) + + " " + (stdoutName ?? NoPipe) + + " " + (stderrName ?? NoPipe) + +#endif +#if NET + string.Join(' ', args); +#elif !NET20 + string.Join(" ", args); +#else + string.Join(" ", args.ToArray()); +#endif + var startInfo = new ProcessStartInfo { UseShellExecute = true, Verb = "runas", FileName = current.MainModule!.FileName!, -#if NET - Arguments = "/elevated " + string.Join(' ', args), -#elif !NET20 - Arguments = "/elevated " + string.Join(" ", args), -#else - Arguments = "/elevated " + string.Join(" ", args.ToArray()), -#endif + Arguments = arguments, WindowStyle = ProcessWindowStyle.Hidden, }; @@ -584,6 +633,26 @@ namespace WinSW { using var elevated = Process.Start(startInfo)!; +#if VNEXT + if (stdinName != null) + { + var stdin = new NamedPipeServerStream(stdinName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); + stdin.WaitForConnectionAsync().ContinueWith(_ => Console.OpenStandardInput().CopyToAsync(stdin)); + } + + if (stdoutName != null) + { + var stdout = new NamedPipeServerStream(stdoutName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); + stdout.WaitForConnectionAsync().ContinueWith(_ => stdout.CopyToAsync(Console.OpenStandardOutput())); + } + + if (stderrName != null) + { + var stderr = new NamedPipeServerStream(stderrName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); + stderr.WaitForConnectionAsync().ContinueWith(_ => stderr.CopyToAsync(Console.OpenStandardError())); + } +#endif + elevated.WaitForExit(); Environment.Exit(elevated.ExitCode); } @@ -661,7 +730,7 @@ namespace WinSW var process = ProcessApis.GetCurrentProcess(); if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out var token)) { - ThrowWin32Exception("Failed to open process token."); + Throw.Command.Win32Exception("Failed to open process token."); } try @@ -673,7 +742,7 @@ namespace WinSW sizeof(SecurityApis.TOKEN_ELEVATION), out _)) { - ThrowWin32Exception("Failed to get token information"); + Throw.Command.Win32Exception("Failed to get token information"); } return elevation.TokenIsElevated != 0; @@ -682,12 +751,6 @@ namespace WinSW { _ = HandleApis.CloseHandle(token); } - - static void ThrowWin32Exception(string message) - { - var inner = new Win32Exception(); - throw new Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message); - } } private static string ReadPassword()