protected Process CreateProcessForUap(MethodInfo method, string[] args) { if (method.DeclaringType != typeof(RemotelyInvokable)) { throw new Exception($"Method needs to be defined in {nameof(RemotelyInvokable)} class."); } if (method.Name == nameof(RemotelyInvokable.Sleep)) { return(CreateSleepProcess(int.Parse(args[0]))); } MethodInfo uapMethod = GetMethodForUap(method); string cmdArgs = (string)uapMethod.Invoke(null, args); var p = new Process() { StartInfo = new ProcessStartInfo() { FileName = RunnerName, Arguments = $"/C {PasteArguments.Paste(new string[] { cmdArgs }, false)}" } }; AddProcessForDispose(p); return(p); }
/// <summary>Invokes the method from this assembly in another process using the specified arguments.</summary> /// <param name="method">The method to invoke.</param> /// <param name="args">The arguments to pass to the method.</param> /// <param name="start">true if this function should Start the Process; false if that responsibility is left up to the caller.</param> /// <param name="psi">The ProcessStartInfo to use, or null for a default.</param> /// <param name="pasteArguments">true if this function should paste the arguments (e.g. surrounding with quotes); false if that responsibility is left up to the caller.</param> private static RemoteInvokeHandle RemoteInvoke(MethodInfo method, string[] args, RemoteInvokeOptions options, bool pasteArguments = true) { options = options ?? new RemoteInvokeOptions(); // Verify the specified method returns an int (the exit code) or nothing, // and that if it accepts any arguments, they're all strings. Assert.True(method.ReturnType == typeof(void) || method.ReturnType == typeof(int) || method.ReturnType == typeof(Task <int>)); Assert.All(method.GetParameters(), pi => Assert.Equal(typeof(string), pi.ParameterType)); // And make sure it's in this assembly. This isn't critical, but it helps with deployment to know // that the method to invoke is available because we're already running in this assembly. Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; // Start the other process and return a wrapper for it to handle its lifetime and exit checking. var psi = options.StartInfo; psi.UseShellExecute = false; if (!options.EnableProfiling) { // Profilers / code coverage tools doing coverage of the test process set environment // variables to tell the targeted process what profiler to load. We don't want the child process // to be profiled / have code coverage, so we remove these environment variables for that process // before it's started. psi.Environment.Remove("Cor_Profiler"); psi.Environment.Remove("Cor_Enable_Profiling"); psi.Environment.Remove("CoreClr_Profiler"); psi.Environment.Remove("CoreClr_Enable_Profiling"); } // If we need the host (if it exists), use it, otherwise target the console app directly. string metadataArgs = PasteArguments.Paste(new string[] { a.FullName, t.FullName, method.Name, options.ExceptionFile }, pasteFirstArgumentUsingArgV0Rules: false); string passedArgs = pasteArguments ? PasteArguments.Paste(args, pasteFirstArgumentUsingArgV0Rules: false) : string.Join(" ", args); string testConsoleAppArgs = ExtraParameter + " " + metadataArgs + " " + passedArgs; if (!File.Exists(HostRunner)) { throw new IOException($"{HostRunner} test app isn't present in the test runtime directory."); } if (options.RunAsSudo) { psi.FileName = "sudo"; psi.Arguments = HostRunner + " " + testConsoleAppArgs; } else { psi.FileName = HostRunner; psi.Arguments = testConsoleAppArgs; } // Return the handle to the process, which may or not be started return(new RemoteInvokeHandle(options.Start ? Process.Start(psi) : new Process() { StartInfo = psi }, options)); }
private static void AppendArguments(StringBuilder stringBuilder, Collection <string> argumentList) { if (argumentList.Count > 0) { foreach (string argument in argumentList) { PasteArguments.AppendArgument(stringBuilder, argument); } } }
private static IRemoteInvokeHandle Invoke(MethodInfo method, string[] args, bool pasteArguments = true) { Type t = method.DeclaringType; Assembly a = t.GetTypeInfo().Assembly; string exceptionFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); string resultFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); string metadataArgs = PasteArguments.Paste(new string[] { a.Location, t.FullName, method.Name, exceptionFile }, pasteFirstArgumentUsingArgV0Rules: false); string hostRunner = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName); string passedArgs = pasteArguments ? PasteArguments.Paste(args, pasteFirstArgumentUsingArgV0Rules: false) : string.Join(" ", args); string testConsoleAppArgs = Assembly.GetExecutingAssembly().Location + " " + metadataArgs + " " + passedArgs; ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = hostRunner; psi.Arguments = testConsoleAppArgs; psi.UseShellExecute = false; return(new RemoteInvokeHandle(Process.Start(psi), exceptionFile, resultFile)); }
public override string ToString() => _line ?? PasteArguments.Paste(_args);
public void Paste_Argv0Rules_ThrowsIfQuotes_OnWindows(string argv0) { Assert.Throws <ApplicationException>(() => PasteArguments.Paste(new [] { argv0 }, pasteFirstArgumentUsingArgV0Rules: true)); }
public void Paste_Argv0Rules_Ignored_onUnix(string pasteExpected, string[] arguments) { Assert.Equal(pasteExpected, PasteArguments.Paste(arguments, pasteFirstArgumentUsingArgV0Rules: true)); }
[InlineData(@"app.exe ""\\\\\"""" arg2", new[] { "app.exe", @"\\""", "arg2" })] // 2N backslashes before quote rule public void Pastes(string pasteExpected, string[] arguments) { Assert.Equal(pasteExpected, PasteArguments.Paste(arguments, pasteFirstArgumentUsingArgV0Rules: true)); }