private static string AskServerForUpdate(UpdateCheckRequest requestData)
        {
            int currentBuildNumber = Assembly.GetExecutingAssembly().GetName().Version.Revision;

            string clientGuid = string.Empty;

            if (requestData != null && requestData.ClientGuid != null)
            {
                clientGuid = requestData.ClientGuid;
            }

            bool requestIsFromService = false;

            if (requestData != null)
            {
                requestIsFromService = requestData.RequestIsFromService;
            }

            // Do initial HTTP GET request
            var request = (HttpWebRequest)WebRequest.Create(
                String.Format(k_updateUrl, currentBuildNumber, clientGuid, requestIsFromService));

            request.KeepAlive = false;
            try {
                using (var responseObject = request.GetResponse())
                    using (var responseReader = new StreamReader(responseObject.GetResponseStream())) {
                        return(responseReader.ReadToEnd());
                    }
            } catch (Exception e) {
                ExecuteDelegateSwallowExceptions(requestData.LogWarningHandler,
                                                 "Exception while trying to check for update info.", e);
                return(null);
            }
        }
        private static void SafeLogMessage(object requestDataObject, string logMessage)
        {
            UpdateCheckRequest requestData = (requestDataObject as UpdateCheckRequest);

            if (requestData != null && requestData.LogMessageHandler != null)
            {
                ExecuteDelegateSwallowExceptions(requestData.LogMessageHandler, logMessage);
            }
        }
 internal static void ForceUpdateCheckNow(UpdateCheckRequest requestData, bool resetTimer)
 {
     if (resetTimer)
     {
         s_checkTimer.Change(TimeSpan.Zero, TimeSpan.FromHours(24));
     }
     else
     {
         CheckForAndRunUpdates(requestData);
     }
 }
        internal static void StartUpdateCheckerTimer(UpdateCheckRequest requestData)
        {
            var timeUntilFirstCheck = new TimeSpan((long)(TimeSpan.FromHours(24).Ticks *new Random().NextDouble()));

            if (IsImmediateUpdateCheckFlagSet())
            {
                timeUntilFirstCheck = TimeSpan.FromSeconds(10);

                SafeLogMessage(requestData,
                               "ImmediateUpdateCheck flag is set, but will be subjugated to user preference for automatic updates.");
            }

            s_checkTimer = new System.Threading.Timer(CheckForAndRunUpdates_FromTimer, requestData,
                                                      timeUntilFirstCheck, TimeSpan.FromHours(24));

            SafeLogMessage(requestData, AreAutomaticUpdatesEnabled() ?
                           "Automatic updates are enabled" : "Automatic updates are disabled (by user)");
            SafeLogMessage(requestData, String.Format(
                               "First update check (if enabled) scheduled for t-minus {0} hours",
                               timeUntilFirstCheck.TotalHours));
        }
        private static string AskServerForUpdate(UpdateCheckRequest requestData)
        {
            int currentBuildNumber = Assembly.GetExecutingAssembly().GetName().Version.Revision;

            string clientGuid = string.Empty;
            if (requestData != null && requestData.ClientGuid != null) {
                clientGuid = requestData.ClientGuid;
            }

            bool requestIsFromService = false;
            if (requestData != null) {
                requestIsFromService = requestData.RequestIsFromService;
            }

            // Do initial HTTP GET request
            var request = (HttpWebRequest)WebRequest.Create(
                String.Format(k_updateUrl, currentBuildNumber, clientGuid, requestIsFromService));
            request.KeepAlive = false;
            try {
                using (var responseObject = request.GetResponse())
                using (var responseReader = new StreamReader(responseObject.GetResponseStream())) {
                    return responseReader.ReadToEnd();
                }
            } catch (Exception e) {
                ExecuteDelegateSwallowExceptions(requestData.LogWarningHandler,
                    "Exception while trying to check for update info.", e);
                return null;
            }
        }
        internal static void StartUpdateCheckerTimer(UpdateCheckRequest requestData)
        {
            var timeUntilFirstCheck = new TimeSpan((long)(TimeSpan.FromHours(24).Ticks * new Random().NextDouble()));

            if (IsImmediateUpdateCheckFlagSet()) {
                timeUntilFirstCheck = TimeSpan.FromSeconds(10);

                SafeLogMessage(requestData,
                    "ImmediateUpdateCheck flag is set, but will be subjugated to user preference for automatic updates.");
            }

            s_checkTimer = new System.Threading.Timer(CheckForAndRunUpdates_FromTimer, requestData,
                timeUntilFirstCheck, TimeSpan.FromHours(24));

            SafeLogMessage(requestData, AreAutomaticUpdatesEnabled() ?
                    "Automatic updates are enabled" : "Automatic updates are disabled (by user)");
            SafeLogMessage(requestData, String.Format(
                "First update check (if enabled) scheduled for t-minus {0} hours",
                timeUntilFirstCheck.TotalHours));
        }
 internal static void ForceUpdateCheckNow(UpdateCheckRequest requestData, bool resetTimer)
 {
     if (resetTimer) {
         s_checkTimer.Change(TimeSpan.Zero, TimeSpan.FromHours(24));
     } else {
         CheckForAndRunUpdates(requestData);
     }
 }
        // Note:   could block for a while, but will execute on a ThreadPool thread.
        //
        // Note 2: don't let exceptions bubble past the scope of this function, or else bad things
        //         will happen since it's a ThreadPool thread on .NET 2.0.
        //
        // Note 3: this function in theory should be reentrant, but is not since it's unlikely any
        //         single execution will last for longer than 24 hours (the time for subsequent
        //         invocations).
        //
        // Note 4: it could also be reentrant if the server commands ForceCheckForUpdates(), but that
        //         is also unlikely.
        private static void CheckForAndRunUpdates(object requestDataObject)
        {
            UpdateCheckRequest requestData = null;

            try {
                requestData = (requestDataObject as UpdateCheckRequest ?? new UpdateCheckRequest());

                // try to download update info
                var updateInfoXml = AskServerForUpdate(requestData);
                if (string.IsNullOrEmpty(updateInfoXml))
                {
                    return;
                }

                // decode and verify update info
                var verifiedUpdateInfo = VerifiedUpdateInfo.FromUpdateXml(updateInfoXml,
                                                                          (requestData == null ? false : requestData.AcceptTestCertificate));

                // try to download update executable
                var downloadFileDir = LibraryIO.FindWritableDirectory(CommonDirectories.CurrentExecutingDirectory,
                                                                      CommonDirectories.LocalAppData, CommonDirectories.Temp);
                if (downloadFileDir == null)
                {
                    throw new Exception("Cannot find writable directory for update download.");
                }
                var downloadFilePath = Path.Combine(downloadFileDir, "DesktopBootstrapUpdater.exe");
                if (File.Exists(downloadFilePath))
                {
                    try {
                        File.Delete(downloadFilePath);
                    } catch (IOException ioe) {
                        // this is probably an old update that didn't terminate for some reason.  try to kill it.

                        SafeLogMessage(requestData, "An updater seems to be running already.  Trying to kill it...");

                        int nKilled = 0;
                        foreach (var runningUpdater in Process.GetProcessesByName("DesktopBootstrapUpdater"))
                        {
                            runningUpdater.Kill();
                            nKilled++;
                        }

                        SafeLogMessage(requestData, String.Format("Killed {0} already-running updaters", nKilled));
                    }
                }
                using (var webClient = new WebClient()) {
                    webClient.DownloadFile(verifiedUpdateInfo.DownloadUrl, downloadFilePath);
                }

                // verify downloaded file hash
                string downloadedFileHashBase64;
                using (var fileReader = new FileStream(downloadFilePath, FileMode.Open, FileAccess.Read)) {
                    downloadedFileHashBase64 = Convert.ToBase64String(new SHA1CryptoServiceProvider().ComputeHash(fileReader));
                }
                if (downloadedFileHashBase64 != verifiedUpdateInfo.DownloadHash)
                {
                    throw new Exception("Updater executable hash is mismatched.");
                }

                // we're about the run the updater.  if it sees fit it will TerminateProcess() us, which can
                // leave the tray icon laying behind well after we're gone, sometimes resulting in multiple
                // DesktopBootstrap icons in the system tray.  so instead we're going to hide our tray icon for
                // a little bit, in case the updater wants to kill us (ha!).
                //
                // note, if this update code is executing on DesktopBootstrap.exe, the icon will just be hidden.
                // if it's being ran from the service, then DesktopBootstrap.exe will be asked to close gracefully,
                // which should remove the tray icon BUT if the update doesn't restart DesktopBootstrap.exe then it
                // won't be restarted until the next machine reboot.
                try {
                    if (requestData.BeforeExecutingUpdateFile != null)
                    {
                        requestData.BeforeExecutingUpdateFile();
                    }
                } catch (Exception eBeforeExecuting) {
                    if (requestData != null && requestData.LogWarningHandler != null)
                    {
                        ExecuteDelegateSwallowExceptions(requestData.LogWarningHandler,
                                                         "Exception calling BeforeExecutingUpdateFile delegate", eBeforeExecuting);
                    }
                }

                SafeLogMessage(requestData, String.Format("Launching update executable {0}", downloadFilePath));

                Process.Start(downloadFilePath);
            } catch (Exception e) {
                if (requestData != null && requestData.LogErrorHandler != null)
                {
                    ExecuteDelegateSwallowExceptions(requestData.LogErrorHandler,
                                                     "Exception while checking for and running updates", e);
                }
            }
        }