コード例 #1
0
ファイル: Elevator.cs プロジェクト: zigmaweb/CS.Util
        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));
        }
コード例 #2
0
ファイル: Elevator.cs プロジェクト: zigmaweb/CS.Util
            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.");
                }
            }