Ejemplo n.º 1
0
        public static int RunFromMostRecent(System.Reflection.MethodInfo method, string[] cmdargs, AutoUpdateStrategy defaultstrategy = AutoUpdateStrategy.InstallDuring)
        {
            // If the update is disabled, go straight in
            if (DISABLE_UPDATE_DOMAIN)
            {
                return(RunMethod(method, cmdargs));
            }

            // If we are not the primary domain, just execute
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
            {
                int r = 0;
                WrapWithUpdater(defaultstrategy, () => {
                    r = RunMethod(method, cmdargs);
                });

                return(r);
            }

            // If we are a re-launch, wait briefly for the other process to exit
            var sleepmarker = System.Environment.GetEnvironmentVariable(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME));

            if (!string.IsNullOrWhiteSpace(sleepmarker))
            {
                System.Environment.SetEnvironmentVariable(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME), null);
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
            }

            // Check if there are updates installed, otherwise use current
            KeyValuePair <string, UpdateInfo> best = new KeyValuePair <string, UpdateInfo>(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, SelfVersion);

            if (HasUpdateInstalled)
            {
                best = m_hasUpdateInstalled.Value;
            }

            if (INSTALLDIR != null && System.IO.File.Exists(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE)))
            {
                try
                {
                    var current = System.IO.File.ReadAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE)).Trim();
                    if (!string.IsNullOrWhiteSpace(current))
                    {
                        var targetfolder    = System.IO.Path.Combine(INSTALLDIR, current);
                        var currentmanifest = ReadInstalledManifest(targetfolder);
                        if (currentmanifest != null && VerifyUnpackedFolder(targetfolder, currentmanifest))
                        {
                            best = new KeyValuePair <string, UpdateInfo>(targetfolder, currentmanifest);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                    {
                        OnError(ex);
                    }
                }
            }

            Environment.SetEnvironmentVariable(string.Format(INSTALLDIR_ENVNAME_TEMPLATE, APPNAME), InstalledBaseDir);

            var folder = best.Key;

            // Basic idea with the loop is that the running AppDomain can use
            // RUN_UPDATED_ENVNAME_TEMPLATE to signal that a new version is ready
            // when the caller exits, the new update is executed
            //
            // This allows more or less seamless updates
            //

            int result = 0;

            while (!string.IsNullOrWhiteSpace(folder) && System.IO.Directory.Exists(folder))
            {
                var prevfolder = folder;
                // Create the new domain
                var domain = AppDomain.CreateDomain(
                    "UpdateDomain",
                    null,
                    folder,
                    "",
                    false
                    );

                result = domain.ExecuteAssemblyByName(method.DeclaringType.Assembly.GetName().Name, cmdargs);

                folder = (string)domain.GetData(RUN_UPDATED_FOLDER_PATH);

                try { AppDomain.Unload(domain); }
                catch (Exception ex)
                {
                    Console.WriteLine("Appdomain unload error: {0}", ex);
                }

                if (!string.IsNullOrWhiteSpace(folder))
                {
                    if (!VerifyUnpackedFolder(folder))
                    {
                        folder = prevfolder; //Go back and run the previous version
                    }
                    else if (RequiresRespawn)
                    {
                        // We have a valid update, and the current instance is terminated.
                        // But due to external libraries, we need to re-spawn the original process

                        try
                        {
                            var args = Environment.CommandLine;
                            var app  = Environment.GetCommandLineArgs().First();
                            args = args.Substring(app.Length);

                            if (!System.IO.Path.IsPathRooted(app))
                            {
                                app = System.IO.Path.Combine(InstalledBaseDir, app);
                            }


                            // Re-launch but give the OS a little time to fully unload all open handles, etc.
                            var si = new System.Diagnostics.ProcessStartInfo(app, args);
                            si.UseShellExecute = false;
                            si.EnvironmentVariables.Add(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME), "1");

                            System.Diagnostics.Process.Start(si);

                            return(0);
                        }
                        catch (Exception ex)
                        {
                            if (OnError != null)
                            {
                                OnError(ex);
                            }
                            folder = prevfolder;
                        }
                    }
                }
            }

            return(result);
        }
Ejemplo n.º 2
0
        private static void WrapWithUpdater(AutoUpdateStrategy defaultstrategy, Action wrappedFunction)
        {
            string optstr = Environment.GetEnvironmentVariable(string.Format(UPDATE_STRATEGY_ENVNAME_TEMPLATE, APPNAME));
            AutoUpdateStrategy strategy;
            if (string.IsNullOrWhiteSpace(optstr) || !Enum.TryParse(optstr, out strategy))
                strategy = defaultstrategy;

            System.Threading.Thread backgroundChecker = null;
            UpdateInfo updateDetected = null;
            bool updateInstalled = false;

            bool checkForUpdate;
            bool downloadUpdate;
            bool runAfter;
            bool runDuring;
            bool runBefore;

            switch (strategy)
            {
                case AutoUpdateStrategy.CheckBefore:
                case AutoUpdateStrategy.CheckDuring:
                case AutoUpdateStrategy.CheckAfter:
                    checkForUpdate = true;
                    downloadUpdate = false;
                    break;

                case AutoUpdateStrategy.InstallBefore:
                case AutoUpdateStrategy.InstallDuring:
                case AutoUpdateStrategy.InstallAfter:
                    checkForUpdate = true;
                    downloadUpdate = true;
                    break;

                default:
                    checkForUpdate = false;
                    downloadUpdate = false;
                    break;
            }

            switch (strategy)
            {
                case AutoUpdateStrategy.CheckBefore:
                case AutoUpdateStrategy.InstallBefore:
                    runBefore = true;
                    runDuring = false;
                    runAfter = false;
                    break;

                case AutoUpdateStrategy.CheckAfter:
                case AutoUpdateStrategy.InstallAfter:
                    runBefore = false;
                    runDuring = false;
                    runAfter = true;
                    break;

                case AutoUpdateStrategy.CheckDuring:
                case AutoUpdateStrategy.InstallDuring:
                    runBefore = false;
                    runDuring = true;
                    runAfter = false;
                    break;

                default:
                    runBefore = false;
                    runDuring = false;
                    runAfter = false;
                    break;
            }

            if (checkForUpdate)
            {
                backgroundChecker = new System.Threading.Thread(() =>
                {
                    // Don't run "during" if the task is short
                    if (runDuring)
                        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));

                    updateDetected = CheckForUpdate();
                    if (updateDetected != null && downloadUpdate)
                    {
                        if (!runDuring)
                            Console.WriteLine("Update to {0} detected, installing...", updateDetected.Displayname);
                        updateInstalled = DownloadAndUnpackUpdate(updateDetected);
                    }
                });

                backgroundChecker.IsBackground = true;
                backgroundChecker.Name = "BackgroundUpdateChecker";

                if (!runAfter)
                    backgroundChecker.Start();

                if (runBefore)
                {
                    Console.WriteLine("Checking for update ...");
                    backgroundChecker.Join();

                    if (downloadUpdate)
                    {
                        if (updateInstalled)
                            Console.WriteLine("Install succeeded, running updated version");
                        else
                            Console.WriteLine("Install or download failed, using current version");
                    }
                    else if (updateDetected != null)
                    {
                        Console.WriteLine("Update \"{0}\" detected", updateDetected.Displayname);
                    }

                    backgroundChecker = null;
                }
            }

            wrappedFunction();

            if (backgroundChecker != null && runAfter)
            {
                Console.WriteLine("Checking for update ...");

                backgroundChecker.Start();
                backgroundChecker.Join();
            }

            if (backgroundChecker != null && updateDetected != null)
            {
                if (backgroundChecker.IsAlive)
                {
                    Console.WriteLine("Waiting for update \"{0}\" to complete", updateDetected.Displayname);
                    backgroundChecker.Join();
                }

                if (downloadUpdate)
                {
                    if (updateInstalled)
                        Console.WriteLine("Install succeeded, running updated version on next launch");
                    else
                        Console.WriteLine("Install or download failed, using current version on next launch");
                }
                else
                {
                    Console.WriteLine("Update \"{0}\" detected", updateDetected.Displayname);
                }
            }
        }
Ejemplo n.º 3
0
        private static void WrapWithUpdater(AutoUpdateStrategy defaultstrategy, Action wrappedFunction)
        {
            string             optstr = Environment.GetEnvironmentVariable(string.Format(UPDATE_STRATEGY_ENVNAME_TEMPLATE, APPNAME));
            AutoUpdateStrategy strategy;

            if (string.IsNullOrWhiteSpace(optstr) || !Enum.TryParse(optstr, out strategy))
            {
                strategy = defaultstrategy;
            }

            System.Threading.Thread backgroundChecker = null;
            UpdateInfo updateDetected  = null;
            bool       updateInstalled = false;

            bool checkForUpdate;
            bool downloadUpdate;
            bool runAfter;
            bool runDuring;
            bool runBefore;


            switch (strategy)
            {
            case AutoUpdateStrategy.CheckBefore:
            case AutoUpdateStrategy.CheckDuring:
            case AutoUpdateStrategy.CheckAfter:
                checkForUpdate = true;
                downloadUpdate = false;
                break;

            case AutoUpdateStrategy.InstallBefore:
            case AutoUpdateStrategy.InstallDuring:
            case AutoUpdateStrategy.InstallAfter:
                checkForUpdate = true;
                downloadUpdate = true;
                break;

            default:
                checkForUpdate = false;
                downloadUpdate = false;
                break;
            }

            switch (strategy)
            {
            case AutoUpdateStrategy.CheckBefore:
            case AutoUpdateStrategy.InstallBefore:
                runBefore = true;
                runDuring = false;
                runAfter  = false;
                break;

            case AutoUpdateStrategy.CheckAfter:
            case AutoUpdateStrategy.InstallAfter:
                runBefore = false;
                runDuring = false;
                runAfter  = true;
                break;

            case AutoUpdateStrategy.CheckDuring:
            case AutoUpdateStrategy.InstallDuring:
                runBefore = false;
                runDuring = true;
                runAfter  = false;
                break;

            default:
                runBefore = false;
                runDuring = false;
                runAfter  = false;
                break;
            }

            if (checkForUpdate)
            {
                backgroundChecker = new System.Threading.Thread(() =>
                {
                    // Don't run "during" if the task is short
                    if (runDuring)
                    {
                        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
                    }

                    updateDetected = CheckForUpdate();
                    if (updateDetected != null && downloadUpdate)
                    {
                        if (!runDuring)
                        {
                            Console.WriteLine("Update to {0} detected, installing...", updateDetected.Displayname);
                        }
                        updateInstalled = DownloadAndUnpackUpdate(updateDetected);
                    }
                });

                backgroundChecker.IsBackground = true;
                backgroundChecker.Name         = "BackgroundUpdateChecker";

                if (!runAfter)
                {
                    backgroundChecker.Start();
                }

                if (runBefore)
                {
                    Console.WriteLine("Checking for update ...");
                    backgroundChecker.Join();

                    if (downloadUpdate)
                    {
                        if (updateInstalled)
                        {
                            Console.WriteLine("Install succeeded, running updated version");
                        }
                        else
                        {
                            Console.WriteLine("Install or download failed, using current version");
                        }
                    }
                    else if (updateDetected != null)
                    {
                        Console.WriteLine("Update \"{0}\" detected", updateDetected.Displayname);
                    }

                    backgroundChecker = null;
                }
            }

            wrappedFunction();

            if (backgroundChecker != null && runAfter)
            {
                Console.WriteLine("Checking for update ...");

                backgroundChecker.Start();
                backgroundChecker.Join();
            }

            if (backgroundChecker != null && updateDetected != null)
            {
                if (backgroundChecker.IsAlive)
                {
                    Console.WriteLine("Waiting for update \"{0}\" to complete", updateDetected.Displayname);
                    backgroundChecker.Join();
                }

                if (downloadUpdate)
                {
                    if (updateInstalled)
                    {
                        Console.WriteLine("Install succeeded, running updated version on next launch");
                    }
                    else
                    {
                        Console.WriteLine("Install or download failed, using current version on next launch");
                    }
                }
                else
                {
                    Console.WriteLine("Update \"{0}\" detected", updateDetected.Displayname);
                }
            }
        }
Ejemplo n.º 4
0
        public static int RunFromMostRecent(System.Reflection.MethodInfo method, string[] cmdargs, AutoUpdateStrategy defaultstrategy = AutoUpdateStrategy.CheckDuring)
        {
            // If the update is disabled, go straight in
            if (DISABLE_UPDATE_DOMAIN)
                return RunMethod(method, cmdargs);

            // If we are not the primary domain, just execute
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
            {
                int r = 0;
                WrapWithUpdater(defaultstrategy, () => {
                    r = RunMethod(method, cmdargs);
                });

                return r;
            }

            // If we are a re-launch, wait briefly for the other process to exit
            var sleepmarker = System.Environment.GetEnvironmentVariable(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME));
            if (!string.IsNullOrWhiteSpace(sleepmarker))
            {
                System.Environment.SetEnvironmentVariable(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME), null);
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));
            }

            // Check if there are updates installed, otherwise use current
            KeyValuePair<string, UpdateInfo> best = new KeyValuePair<string, UpdateInfo>(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, SelfVersion);
            if (HasUpdateInstalled)
                best = m_hasUpdateInstalled.Value;

            if (INSTALLDIR != null && System.IO.File.Exists(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE)))
            {
                try
                {
                    var current = System.IO.File.ReadAllText(System.IO.Path.Combine(INSTALLDIR, CURRENT_FILE)).Trim();
                    if (!string.IsNullOrWhiteSpace(current))
                    {
                        var targetfolder = System.IO.Path.Combine(INSTALLDIR, current);
                        var currentmanifest = ReadInstalledManifest(targetfolder);
                        if (currentmanifest != null && VerifyUnpackedFolder(targetfolder, currentmanifest))
                            best = new KeyValuePair<string, UpdateInfo>(targetfolder, currentmanifest);
                    }
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                        OnError(ex);
                }
            }

            Environment.SetEnvironmentVariable(string.Format(INSTALLDIR_ENVNAME_TEMPLATE, APPNAME), InstalledBaseDir);

            var folder = best.Key;

            // Basic idea with the loop is that the running AppDomain can use
            // RUN_UPDATED_ENVNAME_TEMPLATE to signal that a new version is ready
            // when the caller exits, the new update is executed
            //
            // This allows more or less seamless updates
            //

            int result = 0;
            while (!string.IsNullOrWhiteSpace(folder) && System.IO.Directory.Exists(folder))
            {
                var prevfolder = folder;
                // Create the new domain
                var domain = AppDomain.CreateDomain(
                                 "UpdateDomain",
                                 null,
                                 folder,
                                 "",
                                 false
                             );

                result = domain.ExecuteAssemblyByName(method.DeclaringType.Assembly.GetName().Name, cmdargs);

                folder = (string)domain.GetData(RUN_UPDATED_FOLDER_PATH);

                try { AppDomain.Unload(domain); }
                catch (Exception ex)
                {
                    Console.WriteLine("Appdomain unload error: {0}", ex);
                }

                if (!string.IsNullOrWhiteSpace(folder))
                {
                    if (!VerifyUnpackedFolder(folder))
                        folder = prevfolder; //Go back and run the previous version
                    else if (RequiresRespawn)
                    {
                        // We have a valid update, and the current instance is terminated.
                        // But due to external libraries, we need to re-spawn the original process

                        try
                        {
                            var args = Environment.CommandLine;
                            var app = Environment.GetCommandLineArgs().First();
                            args = args.Substring(app.Length);

                            if (!System.IO.Path.IsPathRooted(app))
                                app = System.IO.Path.Combine(InstalledBaseDir, app);

                            // Re-launch but give the OS a little time to fully unload all open handles, etc.
                            var si = new System.Diagnostics.ProcessStartInfo(app, args);
                            si.UseShellExecute = false;
                            si.EnvironmentVariables.Add(string.Format(SLEEP_ENVNAME_TEMPLATE, APPNAME), "1");

                            System.Diagnostics.Process.Start(si);

                            return 0;
                        }
                        catch (Exception ex)
                        {
                            if (OnError != null)
                                OnError(ex);
                            folder = prevfolder;
                        }
                    }
                }
            }

            return result;
        }