From 063387bab2d0b1d721c71c347bb72b9bb3b96ba8 Mon Sep 17 00:00:00 2001 From: Xavier Zwirtz Date: Sat, 8 May 2021 14:48:31 -0500 Subject: [PATCH] add ability to specify launched process filename and args --- src/Tmds.ExecFunction/ExecFunction.cs | 204 ++++++++++++---------- src/Tmds.ExecFunction/FunctionExecutor.cs | 52 +++--- 2 files changed, 137 insertions(+), 119 deletions(-) diff --git a/src/Tmds.ExecFunction/ExecFunction.cs b/src/Tmds.ExecFunction/ExecFunction.cs index bd3193d..c950bc4 100644 --- a/src/Tmds.ExecFunction/ExecFunction.cs +++ b/src/Tmds.ExecFunction/ExecFunction.cs @@ -16,87 +16,91 @@ namespace Tmds.Utils { public static partial class ExecFunction { - public static Process Start(Action action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure).process; + public static Process Start(Action action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Action action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure).process; + public static Process Start(Action action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure).process; + public static Process Start(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure).process; + public static Process Start(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure).process; + public static Process Start(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure).process; + public static Process Start(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func> action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure).process; + public static Process Start(Func> action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static Process Start(Func> action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure).process; + public static Process Start(Func> action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, execFunctionHostArgs: execFunctionHostArgs).process; - public static void Run(Action action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true); + public static void Run(Action action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Action action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true); + public static void Run(Action action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true); + public static void Run(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true); + public static void Run(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true); + public static void Run(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true); + public static void Run(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func> action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true); + public static void Run(Func> action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static void Run(Func> action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true); + public static void Run(Func> action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, waitForExit: true, execFunctionHostArgs: execFunctionHostArgs); - public static Task RunAsync(Action action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true).exitedTask; + public static Task RunAsync(Action action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Action action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true).exitedTask; + public static Task RunAsync(Action action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func> action, Action configure = null) - => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func> action, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), Array.Empty(), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - public static Task RunAsync(Func> action, string[] args, Action configure = null) - => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true).exitedTask; + public static Task RunAsync(Func> action, string[] args, Action configure = null, ExecFunctionHostArgs execFunctionHostArgs = null) + => Start(GetMethodInfo(action), args ?? throw new ArgumentNullException(nameof(args)), configure, returnTask: true, execFunctionHostArgs: execFunctionHostArgs).exitedTask; - private static (Process process, Task exitedTask) Start(MethodInfo method, string[] args, Action configure, bool waitForExit = false, bool returnTask = false) + private static (Process process, Task exitedTask) Start(MethodInfo method, string[] args, Action configure, ExecFunctionHostArgs execFunctionHostArgs = null, bool waitForExit = false, bool returnTask = false) { Process process = null; try { process = new Process(); + if(execFunctionHostArgs == null) { + execFunctionHostArgs = _execFunctiohHostArgsDefault.Value; + } + ExecFunctionOptions options = new ExecFunctionOptions(process.StartInfo); - ConfigureProcessStartInfoForMethodInvocation(method, args, options.StartInfo); + ConfigureProcessStartInfoForMethodInvocation(method, args, options.StartInfo, execFunctionHostArgs); configure?.Invoke(options); TaskCompletionSource tcs = null; @@ -143,7 +147,7 @@ private static (Process process, Task exitedTask) Start(MethodInfo method, strin } } - private static void ConfigureProcessStartInfoForMethodInvocation(MethodInfo method, string[] args, ProcessStartInfo psi) + private static void ConfigureProcessStartInfoForMethodInvocation(MethodInfo method, string[] args, ProcessStartInfo psi, ExecFunctionHostArgs execFunctionHostArgs) { if (method.ReturnType != typeof(void) && method.ReturnType != typeof(int) && @@ -165,9 +169,9 @@ private static void ConfigureProcessStartInfoForMethodInvocation(MethodInfo meth Assembly a = t.GetTypeInfo().Assembly; string programArgs = PasteArguments.Paste(new string[] { a.FullName, t.FullName, method.Name }); string functionArgs = PasteArguments.Paste(args); - string fullArgs = HostArguments + " " + " " + programArgs + " " + functionArgs; + string fullArgs = execFunctionHostArgs.HostArguments + " " + " " + programArgs + " " + functionArgs; - psi.FileName = HostFilename; + psi.FileName = execFunctionHostArgs.HostFilename; psi.Arguments = fullArgs; } @@ -198,62 +202,76 @@ private static MethodInfo GetMethodInfo(Delegate d) return d.GetMethodInfo(); } - static ExecFunction() - { - HostFilename = Process.GetCurrentProcess().MainModule.FileName; - string[] appArguments = null; - // application is running as 'testhost' - // try to find parent 'dotnet' host process. - if (HostFilename.EndsWith("/testhost") || HostFilename.EndsWith("\\testhost.exe")) + private static Lazy _execFunctiohHostArgsDefault = + new Lazy(() => new ExecFunctionHostArgs(typeof(ExecFunction).Assembly.Location)); + + public class ExecFunctionHostArgs + { + public ExecFunctionHostArgs(string execFunctionAssembly) { - HostFilename = null; + HostFilename = Process.GetCurrentProcess().MainModule.FileName; + string[] appArguments = null; - appArguments = GetApplicationArguments(); - string parentProcessIdRaw = GetApplicationArgument(appArguments, "--parentprocessid"); - if (parentProcessIdRaw != null) + // application is running as 'testhost' + // try to find parent 'dotnet' host process. + if (HostFilename.EndsWith("/testhost") || HostFilename.EndsWith("\\testhost.exe")) { - int parentProcessId = int.Parse(parentProcessIdRaw); + HostFilename = null; + + appArguments = GetApplicationArguments(); + string parentProcessIdRaw = GetApplicationArgument(appArguments, "--parentprocessid"); + if (parentProcessIdRaw != null) + { + int parentProcessId = int.Parse(parentProcessIdRaw); + + Process proc = Process.GetProcessById(parentProcessId); + HostFilename = proc.MainModule.FileName; + } - Process proc = Process.GetProcessById(parentProcessId); - HostFilename = proc.MainModule.FileName; + if (HostFilename == null || + !((HostFilename.EndsWith("/dotnet") || HostFilename.EndsWith("\\dotnet.exe")))) + { + throw new NotSupportedException("Application is running as testhost, unable to determine parent 'dotnet' process."); + } } - if (HostFilename == null || - !((HostFilename.EndsWith("/dotnet") || HostFilename.EndsWith("\\dotnet.exe")))) + // application is running as 'dotnet exec'. + if (HostFilename.EndsWith("/dotnet") || HostFilename.EndsWith("\\dotnet.exe")) { - throw new NotSupportedException("Application is running as testhost, unable to determine parent 'dotnet' process."); - } - } + string entryAssemblyWithoutExtension = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), + Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location)); + appArguments = appArguments ?? GetApplicationArguments(); - // application is running as 'dotnet exec'. - if (HostFilename.EndsWith("/dotnet") || HostFilename.EndsWith("\\dotnet.exe")) - { - string execFunctionAssembly = typeof(ExecFunction).Assembly.Location; + string runtimeConfigFile = GetApplicationArgument(appArguments, "--runtimeconfig"); + if (runtimeConfigFile == null) + { + runtimeConfigFile = entryAssemblyWithoutExtension + ".runtimeconfig.json"; + } - string entryAssemblyWithoutExtension = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), - Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location)); - appArguments = appArguments ?? GetApplicationArguments(); + string depsFile = GetApplicationArgument(appArguments, "--depsfile"); + if (depsFile == null) + { + depsFile = entryAssemblyWithoutExtension + ".deps.json"; + } - string runtimeConfigFile = GetApplicationArgument(appArguments, "--runtimeconfig"); - if (runtimeConfigFile == null) - { - runtimeConfigFile = entryAssemblyWithoutExtension + ".runtimeconfig.json"; + HostArguments = PasteArguments.Paste(new string[] { "exec", "--runtimeconfig", runtimeConfigFile, "--depsfile", depsFile, execFunctionAssembly }); } - - string depsFile = GetApplicationArgument(appArguments, "--depsfile"); - if (depsFile == null) + // application is an apphost. Main method must call 'RunFunction.Program.Main' for CommandName. + else { - depsFile = entryAssemblyWithoutExtension + ".deps.json"; + HostArguments = CommandName; } - - HostArguments = PasteArguments.Paste(new string[] { "exec", "--runtimeconfig", runtimeConfigFile, "--depsfile", depsFile, execFunctionAssembly }); } - // application is an apphost. Main method must call 'RunFunction.Program.Main' for CommandName. - else + + public ExecFunctionHostArgs(string HostFilename, string HostArguments) { - HostArguments = CommandName; + this.HostFilename = HostFilename; + this.HostArguments = HostArguments; } + + public readonly string HostFilename; + public readonly string HostArguments; } private static string GetApplicationArgument(string[] arguments, string name) @@ -422,7 +440,5 @@ public static string[] CommandLineToArgs(string commandLine) } } - private static readonly string HostFilename; - private static readonly string HostArguments; } } diff --git a/src/Tmds.ExecFunction/FunctionExecutor.cs b/src/Tmds.ExecFunction/FunctionExecutor.cs index 66695b5..3c897ad 100644 --- a/src/Tmds.ExecFunction/FunctionExecutor.cs +++ b/src/Tmds.ExecFunction/FunctionExecutor.cs @@ -11,82 +11,84 @@ namespace Tmds.Utils public class FunctionExecutor { private readonly Action _configure; + private readonly ExecFunction.ExecFunctionHostArgs _execFunctionHostArgs; - public FunctionExecutor(Action configure) + public FunctionExecutor(Action configure, ExecFunction.ExecFunctionHostArgs execFunctionHostArgs = null) { _configure = configure; + _execFunctionHostArgs = execFunctionHostArgs; } public Process Start(Action action, Action configure = null) - => ExecFunction.Start(action, _configure + configure); + => ExecFunction.Start(action, _configure + configure.Invoke, _execFunctionHostArgs); public Process Start(Action action, string[] args, Action configure = null) - => ExecFunction.Start(action, args, _configure + configure); + => ExecFunction.Start(action, args, _configure + configure, _execFunctionHostArgs); public Process Start(Func action, Action configure = null) - => ExecFunction.Start(action, _configure + configure); + => ExecFunction.Start(action, _configure + configure, _execFunctionHostArgs); public Process Start(Func action, string[] args, Action configure = null) - => ExecFunction.Start(action, args, _configure + configure); + => ExecFunction.Start(action, args, _configure + configure, _execFunctionHostArgs); public Process Start(Func action, Action configure = null) - => ExecFunction.Start(action, _configure + configure); + => ExecFunction.Start(action, _configure + configure, _execFunctionHostArgs); public Process Start(Func action, string[] args, Action configure = null) - => ExecFunction.Start(action, args, _configure + configure); + => ExecFunction.Start(action, args, _configure + configure, _execFunctionHostArgs); public Process Start(Func> action, Action configure = null) - => ExecFunction.Start(action, _configure + configure); + => ExecFunction.Start(action, _configure + configure, _execFunctionHostArgs); public Process Start(Func> action, string[] args, Action configure = null) - => ExecFunction.Start(action, args, _configure + configure); + => ExecFunction.Start(action, args, _configure + configure, _execFunctionHostArgs); public void Run(Action action, Action configure = null) - => ExecFunction.Run(action, _configure + configure); + => ExecFunction.Run(action, _configure + configure, _execFunctionHostArgs); public void Run(Action action, string[] args, Action configure = null) - => ExecFunction.Run(action, args, _configure + configure); + => ExecFunction.Run(action, args, _configure + configure, _execFunctionHostArgs); public void Run(Func action, Action configure = null) - => ExecFunction.Run(action, _configure + configure); + => ExecFunction.Run(action, _configure + configure, _execFunctionHostArgs); public void Run(Func action, string[] args, Action configure = null) - => ExecFunction.Run(action, args, _configure + configure); + => ExecFunction.Run(action, args, _configure + configure, _execFunctionHostArgs); public void Run(Func action, Action configure = null) - => ExecFunction.Run(action, _configure + configure); + => ExecFunction.Run(action, _configure + configure, _execFunctionHostArgs); public void Run(Func action, string[] args, Action configure = null) - => ExecFunction.Run(action, args, _configure + configure); + => ExecFunction.Run(action, args, _configure + configure, _execFunctionHostArgs); public void Run(Func> action, Action configure = null) - => ExecFunction.Run(action, _configure + configure); + => ExecFunction.Run(action, _configure + configure, _execFunctionHostArgs); public void Run(Func> action, string[] args, Action configure = null) - => ExecFunction.Run(action, args, _configure + configure); + => ExecFunction.Run(action, args, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Action action, Action configure = null) - => ExecFunction.RunAsync(action, _configure + configure); + => ExecFunction.RunAsync(action, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Action action, string[] args, Action configure = null) - => ExecFunction.RunAsync(action, args, _configure + configure); + => ExecFunction.RunAsync(action, args, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func action, Action configure = null) - => ExecFunction.RunAsync(action, _configure + configure); + => ExecFunction.RunAsync(action, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func action, string[] args, Action configure = null) - => ExecFunction.RunAsync(action, args, _configure + configure); + => ExecFunction.RunAsync(action, args, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func action, Action configure = null) - => ExecFunction.RunAsync(action, _configure + configure); + => ExecFunction.RunAsync(action, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func action, string[] args, Action configure = null) - => ExecFunction.RunAsync(action, args, _configure + configure); + => ExecFunction.RunAsync(action, args, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func> action, Action configure = null) - => ExecFunction.RunAsync(action, _configure + configure); + => ExecFunction.RunAsync(action, _configure + configure, _execFunctionHostArgs); public Task RunAsync(Func> action, string[] args, Action configure = null) - => ExecFunction.RunAsync(action, args, _configure + configure); + => ExecFunction.RunAsync(action, args, _configure + configure, _execFunctionHostArgs); } } \ No newline at end of file