mirror of https://github.com/winsw/winsw
Redirect I/O of elevated process (#719)
parent
03930a23d2
commit
48015a5d7a
|
@ -287,7 +287,6 @@ namespace WinSW.Configuration
|
||||||
{
|
{
|
||||||
if (!int.TryParse(this.ZipOlderThanNumDaysYamlLog, out int zipolderthannumdaysValue))
|
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.");
|
throw new InvalidDataException("Roll-Size-Time Based rolling policy is specified but zipOlderThanNumDays does not match the int format found in configuration XML.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace WinSW
|
||||||
public class ServiceDescriptor : IWinSWConfiguration
|
public class ServiceDescriptor : IWinSWConfiguration
|
||||||
{
|
{
|
||||||
protected readonly XmlDocument dom = new();
|
protected readonly XmlDocument dom = new();
|
||||||
|
|
||||||
private readonly Dictionary<string, string> environmentVariables;
|
private readonly Dictionary<string, string> environmentVariables;
|
||||||
|
|
||||||
public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings();
|
public static DefaultWinSWSettings Defaults { get; } = new DefaultWinSWSettings();
|
||||||
|
|
|
@ -3,6 +3,9 @@ using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
#if VNEXT
|
||||||
|
using System.IO.Pipes;
|
||||||
|
#endif
|
||||||
#if NET
|
#if NET
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,6 +31,10 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
|
#if VNEXT
|
||||||
|
private const string NoPipe = "-";
|
||||||
|
#endif
|
||||||
|
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||||
|
|
||||||
public static int Main(string[] args)
|
public static int Main(string[] args)
|
||||||
|
@ -127,7 +134,35 @@ namespace WinSW
|
||||||
_ = ConsoleApis.FreeConsole();
|
_ = ConsoleApis.FreeConsole();
|
||||||
_ = ConsoleApis.AttachConsole(ConsoleApis.ATTACH_PARENT_PROCESS);
|
_ = 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);
|
args = args.GetRange(1, args.Count - 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (Environment.OSVersion.Version.Major == 5)
|
else if (Environment.OSVersion.Version.Major == 5)
|
||||||
{
|
{
|
||||||
|
@ -565,18 +600,32 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
using var current = Process.GetCurrentProcess();
|
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
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = "runas",
|
Verb = "runas",
|
||||||
FileName = current.MainModule!.FileName!,
|
FileName = current.MainModule!.FileName!,
|
||||||
#if NET
|
Arguments = arguments,
|
||||||
Arguments = "/elevated " + string.Join(' ', args),
|
|
||||||
#elif !NET20
|
|
||||||
Arguments = "/elevated " + string.Join(" ", args),
|
|
||||||
#else
|
|
||||||
Arguments = "/elevated " + string.Join(" ", args.ToArray()),
|
|
||||||
#endif
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -584,6 +633,26 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
using var elevated = Process.Start(startInfo)!;
|
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();
|
elevated.WaitForExit();
|
||||||
Environment.Exit(elevated.ExitCode);
|
Environment.Exit(elevated.ExitCode);
|
||||||
}
|
}
|
||||||
|
@ -661,7 +730,7 @@ namespace WinSW
|
||||||
var process = ProcessApis.GetCurrentProcess();
|
var process = ProcessApis.GetCurrentProcess();
|
||||||
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out var token))
|
if (!ProcessApis.OpenProcessToken(process, TokenAccessLevels.Read, out var token))
|
||||||
{
|
{
|
||||||
ThrowWin32Exception("Failed to open process token.");
|
Throw.Command.Win32Exception("Failed to open process token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -673,7 +742,7 @@ namespace WinSW
|
||||||
sizeof(SecurityApis.TOKEN_ELEVATION),
|
sizeof(SecurityApis.TOKEN_ELEVATION),
|
||||||
out _))
|
out _))
|
||||||
{
|
{
|
||||||
ThrowWin32Exception("Failed to get token information");
|
Throw.Command.Win32Exception("Failed to get token information");
|
||||||
}
|
}
|
||||||
|
|
||||||
return elevation.TokenIsElevated != 0;
|
return elevation.TokenIsElevated != 0;
|
||||||
|
@ -682,12 +751,6 @@ namespace WinSW
|
||||||
{
|
{
|
||||||
_ = HandleApis.CloseHandle(token);
|
_ = HandleApis.CloseHandle(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ThrowWin32Exception(string message)
|
|
||||||
{
|
|
||||||
var inner = new Win32Exception();
|
|
||||||
throw new Win32Exception(inner.NativeErrorCode, message + ' ' + inner.Message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ReadPassword()
|
private static string ReadPassword()
|
||||||
|
|
Loading…
Reference in New Issue