private static InternalAssemblyRunner InternalGenerate(MethodInfo method, object target, Type[] paramaterTypes, Type returnType, ElevatorOptions options) { if (options == null) { options = new ElevatorOptions(); } if (returnType == null) { returnType = typeof(void); } var assyName = options.AssemblyName; var assyFile = assyName + ".exe"; var dir = Path.Combine(options.TempPath, RandomEx.GetString(8)); Directory.CreateDirectory(dir); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName(assyName), AssemblyBuilderAccess.Save, dir); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assyName, assyFile); var typeBuilder = moduleBuilder.DefineType("Program", TypeAttributes.Class | TypeAttributes.Public); var mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(string[]) }); var dynName = RandomEx.GetString(8); var dynMethod = typeBuilder.DefineMethod(dynName, MethodAttributes.Public | MethodAttributes.Static, returnType, paramaterTypes); var ref1 = EmitModifiedMethod(dynMethod, method, target); var ref2 = EmitMainMethod(mainMethod, dynName, paramaterTypes); typeBuilder.CreateType(); assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication); assemblyBuilder.Save(assyFile); var references = assemblyBuilder.GetReferencedAssemblies() .Select(r => Assembly.ReflectionOnlyLoad(r.FullName)) .Concat(ref1) .Concat(ref2) .Concat(options.Dependancies) .Distinct(new AssemblyFullNameEqualityComparer()) .Where(a => !a.IsInGAC()); foreach (var refAssy in references) { var refName = Path.GetFileName(refAssy.Location); File.Copy(refAssy.Location, Path.Combine(dir, refName)); } return(new InternalAssemblyRunner(Path.Combine(dir, assyFile), paramaterTypes, returnType, options)); }
public object Run(object[] paras) { if (_disposed) { throw new ObjectDisposedException("assyRunner"); } // this should technically never happen... if (!Enumerable.SequenceEqual(paras.Select(s => s.GetType()), _paraTypes)) { throw new ArgumentException("Invoked param types do not match.", nameof(paras)); } var dir = Path.GetDirectoryName(_exePath); var instStr = RandomEx.GetString(8); var argsPath = Path.Combine(dir, instStr) + ".init"; var resultPath = Path.Combine(dir, instStr) + ".result"; List <KeyValuePair <string, object> > wType = paras.Select(o => new KeyValuePair <string, object>(o.GetType().AssemblyQualifiedName, o)) .ToList(); var serialized = SimpleJson.SerializeObject(wType); File.WriteAllText(argsPath, serialized); ProcessStartInfo stInfo = new ProcessStartInfo(_exePath, "\"" + argsPath + "\" \"" + resultPath + "\""); stInfo.CreateNoWindow = true; if (_options.RunElevated) { stInfo.Verb = "runas"; } stInfo.WorkingDirectory = dir; stInfo.UseShellExecute = true; Stopwatch sw = new Stopwatch(); sw.Start(); Process p; try { p = Process.Start(stInfo); } catch (Win32Exception win32ex) { if (win32ex.HResult == -2147467259) { throw new ElevatorException("The option 'RunElevated'=true, and user denied the UAC prompt.", win32ex); } throw; } p.WaitForExit((int)_options.Timeout.TotalMilliseconds); // this is to prevent race conditions with WaitForExit returning before the process has finished cleaning up. if (p.HasExited == false && sw.ElapsedMilliseconds < _options.Timeout.TotalMilliseconds) { Thread.Sleep(20); } sw.Stop(); if (p.HasExited == false) { p.Kill(); throw new TimeoutException("Operation has timed out."); } if (p.ExitCode == 0) // success { if (_returnType == null || _returnType == typeof(void)) { return(null); } else { if (!File.Exists(resultPath)) { throw new ElevatorException("Process exited with code 0 but with not with expected result."); } var resultJson = File.ReadAllText(resultPath); File.Delete(resultPath); if (File.Exists(argsPath)) { File.Delete(argsPath); } try { return(SimpleJson.DeserializeObject(resultJson, _returnType)); } catch (Exception ex) { throw new ElevatorException("Process exited with code 0 but with not with expected result.", ex); } } } else if (p.ExitCode == 1) // exception { if (!File.Exists(resultPath)) { throw new ElevatorException("An unknown exception has occured."); } throw new ElevatorException(File.ReadAllText(resultPath)); } else { throw new ElevatorException("Process returned an invalid and unexpected exit code."); } }