Exemplo n.º 1
0
                public void Boot(MiniInstallerBridge bridge)
                {
                    Assembly installerAssembly = Assembly.LoadFrom(Path.Combine(bridge.ExtractedPath, "MiniInstaller.exe"));
                    Type     installerType     = installerAssembly.GetType("MiniInstaller.Program");

                    // Set up any fields which we can set up by Everest.

                    /*
                     * FieldInfo f_AsmMonoMod = installerType.GetField("AsmMonoMod");
                     * if (f_AsmMonoMod != null)
                     *  f_AsmMonoMod.SetValue(null, typeof(MonoModder).Assembly);
                     */
                    FieldInfo f_LineLogger = installerType.GetField("LineLogger");

                    if (f_LineLogger != null)
                    {
                        // f_LineLogger.SetValue(null, new Action<string>(_ => progress.LogLine(_)).CastDelegate(f_LineLogger.FieldType));
                        f_LineLogger.SetValue(null, new Action <string>(bridge.LogLine).CastDelegate(f_LineLogger.FieldType));
                    }


                    // Let's just run the mod installer... from our mod... while we're running the mod...
                    object exitObject = installerAssembly.EntryPoint.Invoke(null, new object[] { new string[] { } });

                    if (exitObject != null && exitObject is int && ((int)exitObject) != 0)
                    {
                        throw new Exception($"Return code != 0, but {exitObject}");
                    }
                }
            public void Boot(MiniInstallerBridge bridge)
            {
                Assembly installerAssembly = Assembly.LoadFrom(Path.Combine(bridge.Root, "MiniInstaller.exe"));
                Type     installerType     = installerAssembly.GetType("MiniInstaller.Program");

                // Fix MonoMod dying when running with a debugger attached because it's running without a console.
                Hook hookReadKey = new Hook(
                    typeof(Console).GetMethod("ReadKey", BindingFlags.Public | BindingFlags.Static, null, new Type[] { }, null),
                    new Func <ConsoleKeyInfo>(() => {
                    return(new ConsoleKeyInfo('\n', ConsoleKey.Enter, false, false, false));
                })
                    );

                // Fix old versions of MiniInstaller loading HookGen without RuntimeDetour.
                bool loadedRuntimeDetour  = false;
                Hook hookLazyLoadAssembly = new Hook(
                    installerType.GetMethod("LazyLoadAssembly", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(string) }, null),
                    new Func <Func <string, Assembly>, string, Assembly>((orig, path) => {
                    if (path.EndsWith("MonoMod.RuntimeDetour.dll"))
                    {
                        loadedRuntimeDetour = true;
                    }
                    else if (path.EndsWith("MonoMod.RuntimeDetour.HookGen.exe") && !loadedRuntimeDetour)
                    {
                        Console.WriteLine("HACKFIX: Loading MonoMod.RuntimeDetour.dll before MonoMod.RuntimeDetour.HookGen.exe");
                        orig(path.Substring(0, path.Length - 4 - 8) + ".dll");
                    }
                    return(orig(path));
                })
                    );

                TextReader origReader = Console.In;

                using (TextWriter fileWriter = new MiniInstallerBridgeWriter(bridge))
                    using (LogWriter logWriter = new LogWriter {
                        STDOUT = Console.Out,
                        File = fileWriter
                    })
                        using (TextReader fakeReader = new MiniInstallerFakeInReader()) {
                            Console.SetOut(logWriter);
                            Console.SetIn(fakeReader);

                            object exitObject = installerAssembly.EntryPoint.Invoke(null, new object[] { new string[] { } });
                            if (exitObject != null && exitObject is int && ((int)exitObject) != 0)
                            {
                                throw new Exception($"Return code != 0, but {exitObject}");
                            }

                            Console.SetOut(logWriter.STDOUT);
                            logWriter.STDOUT = null;
                            Console.SetIn(origReader);
                        }

                hookReadKey.Undo();
                hookLazyLoadAssembly.Undo();
            }
 public MiniInstallerBridgeWriter(MiniInstallerBridge bridge)
 {
     Bridge = bridge;
 }
Exemplo n.º 4
0
        public static IEnumerator Install(string root)
        {
            Environment.CurrentDirectory = root;

            yield return(StatusSilent("Starting MiniInstaller", false, "monomod", false));

            using (MiniInstallerBridge bridge = new MiniInstallerBridge {
                Encoding = Console.Error.Encoding,
                Root = root
            }) {
                bridge.LogEvent = new ManualResetEvent(false);
                WaitHandle[] waitHandle = new WaitHandle[] { bridge.LogEvent };

                Thread thread = new Thread(() => {
                    AppDomain nest = null;
                    try {
                        AppDomainSetup nestInfo = new AppDomainSetup();
                        // nestInfo.ApplicationBase = Path.GetDirectoryName(root);
                        nestInfo.ApplicationBase    = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
                        nestInfo.LoaderOptimization = LoaderOptimization.SingleDomain;

                        nest = AppDomain.CreateDomain(
                            AppDomain.CurrentDomain.FriendlyName + " - MiniInstaller",
                            AppDomain.CurrentDomain.Evidence,
                            nestInfo,
                            AppDomain.CurrentDomain.PermissionSet
                            );

                        ((MiniInstallerProxy)nest.CreateInstanceAndUnwrap(
                             typeof(MiniInstallerProxy).Assembly.FullName,
                             typeof(MiniInstallerProxy).FullName
                             )).Boot(bridge);

                        AppDomain.Unload(nest);

                        bridge.IsDone = true;
                        bridge.WriteLine("MiniInstaller finished");
                    } catch (Exception e) {
                        bridge.Exception = e;

                        string msg = "MiniInstaller died a brutal death";

                        if (nest != null)
                        {
                            try {
                                AppDomain.Unload(nest);
                            } catch {
                                msg = "MiniInstaller has become a zombie";
                            }
                        }

                        bridge.IsDone = true;
                        bridge.WriteLine(msg);
                        Console.Error.WriteLine(e);
                    }
                })
                {
                    Name = "MiniInstaller"
                };

                thread.Start();

                string lastSent = null;
                while (!bridge.IsDone && thread.IsAlive)
                {
                    WaitHandle.WaitAny(waitHandle, 1000);
                    bridge.LogEvent.Reset();
                    if (lastSent != bridge.LastLogLine)
                    {
                        lastSent = bridge.LastLogLine;
                        yield return(StatusSilent(lastSent, false, "monomod", false));
                    }
                }

                thread.Join();

                if (bridge.Exception != null)
                {
                    throw new Exception("MiniInstaller died a brutal death", bridge.Exception);
                }
            }
        }