コード例 #1
0
        public static void SaveLocalRunInfo(LocalRunInfo localRunInfo)
        {
            var filePath = GetRunInfoJsonFile();
            var jss      = new JavaScriptSerializer();

            File.WriteAllText(filePath, jss.Serialize(localRunInfo), Encoding.UTF8);
        }
コード例 #2
0
        public static void RunMainApp(LocalRunInfo localRunInfo, string msg = null)
        {
            try
            {
                var cmds = localRunInfo.AppRunCmd.Split(new char[] { ' ' },
                                                        StringSplitOptions.RemoveEmptyEntries);
                var exeDir   = Path.GetFullPath(Path.GetDirectoryName(cmds[0]));
                var exeName  = Path.GetFileName(cmds[0]);
                var fileName = Path.Combine(exeDir, exeName);

                if (!File.Exists(fileName))
                {
                    OnMainAppNotExists?.Invoke(localRunInfo); return;
                }

                var args = cmds.Skip(1).Concat(new string[] { "started_by_updater" })
                           .Aggregate(string.Empty, (_args, a) => _args += " " + a);

                RunFile(fileName, args);

                OnMainAppStarted?.Invoke(localRunInfo, msg);
            }
            catch (Exception ex)
            {
                LogHelper.LogErrorToServer($"程序启动失败({msg})", ex, localRunInfo);

                OnError?.Invoke(localRunInfo, ex);
            }
        }
コード例 #3
0
 private void OnNotSpecifyUpdateUrl(LocalRunInfo localRunInfo)
 {
     this.Invoke((Action)(() =>
     {
         InputUpdateUrl(localRunInfo);
     }));
 }
コード例 #4
0
        private void OnMainAppStarted(LocalRunInfo localRunInfo, string msg)
        {
            this.Invoke((Action)(() =>
            {
                if (string.IsNullOrEmpty(localRunInfo.ClientId))
                {
                    localRunInfo.ClientId = InputClientId();
                }

                UpdateHelper.SaveLocalRunInfo(localRunInfo);

                _mainAppPath = localRunInfo.AppRunCmd.Split(new char[] { ' ' },
                                                            StringSplitOptions.RemoveEmptyEntries)[0];
                var urlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);
                this._config = UpdateHelper.GetSystemConfig(urlInfo.Host, urlInfo.SystemId);

                //var urlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);
                //this._config = UpdateHelper.GetSystemConfig(urlInfo.Host, urlInfo.SystemId);

                if (UpdateHelper.IsThisAppRunning() || !this._config.DetectEnabled)
                {// 保证更新程序只有一个在后台运行
                    Exit(localRunInfo);
                }
                else
                {
                    StartUpdateDetect(localRunInfo, this._config);
                    StartMainAppStateDetect(_mainAppPath, localRunInfo, this._config);
                }

                var appName = Path.GetFileName(_mainAppPath);
                notifyIcon.Text = this.Text = "更新检测-" + appName;

                LogHelper.LogInfoToServer($"程序启动成功({msg})", localRunInfo);
            }));
        }
コード例 #5
0
        private static bool IsMainAppRunning(LocalRunInfo localRunInfo)
        {
            var cmds = localRunInfo.AppRunCmd.Split(new char[] { ' ' },
                                                    StringSplitOptions.RemoveEmptyEntries);

            return(IsAppRunning(cmds[0]));
        }
コード例 #6
0
        private void OnUpdateError(LocalRunInfo localRunInfo, Exception ex)
        {
            this.Invoke((Action)(() =>
            {
                LogHelper.LogError("更新出错", ex);
                _frmProgress.Hide();

                if (MessageBox.Show(string.Format("{0}\r\n是否继续运行?", ex.Message),
                                    "错误", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    if (string.IsNullOrEmpty(localRunInfo.AppRunCmd))
                    {
                        InputStartApp(localRunInfo);
                    }
                    else
                    {
                        UpdateHelper.RunMainApp(localRunInfo);
                    }
                }
                else
                {
                    Exit(localRunInfo);
                }
            }));
        }
コード例 #7
0
        public static void LogInfoToServer(string info, LocalRunInfo localRunInfo)
        {
            var updateUrlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);

            string url = $"{updateUrlInfo.Host}/api/LogInfo/{updateUrlInfo.SystemId}?clientId={Util.GetClientId(localRunInfo.ClientId)}&info={info}";

            Util.SendHttpRequest(url);
        }
コード例 #8
0
 private void OnBeginUpdate(LocalRunInfo obj)
 {
     this.Invoke((Action)(() =>
     {
         Hide();
         _frmProgress.Show();
     }));
 }
コード例 #9
0
        private void OnMainAppNotExists(LocalRunInfo localRunInfo)
        {
            this.Invoke((Action)(() =>
            {
                MessageBox.Show("启动程序不存在");

                InputStartApp(localRunInfo);
            }));
        }
コード例 #10
0
        private void OnMainAppAlreadyRunning(LocalRunInfo localRunInfo)
        {
            this.Invoke((Action)(() =>
            {
                MessageBox.Show("程序正在运行,请退出后再更新。", "提示", MessageBoxButtons.OK);

                Exit(localRunInfo);
            }));
        }
コード例 #11
0
 public MainAppStateDetector(string mainAppPath, LocalRunInfo localRunInfo, Config config)
     : base(config.PingInterval * 1000, true)
 {
     this.localRunInfo  = localRunInfo;
     this.mainAppPath   = mainAppPath;
     this.updateUrlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);
     this.clientId      = Util.GetClientId(localRunInfo.ClientId);
     this.config        = config;
 }
コード例 #12
0
        private void OnInvalidUpdateUrl(LocalRunInfo localRunInfo)
        {
            this.Invoke((Action)(() =>
            {
                MessageBox.Show("更新地址有误");

                InputUpdateUrl(localRunInfo);
            }));
        }
コード例 #13
0
        public static void LogErrorToServer(string msg, Exception ex, LocalRunInfo localRunInfo)
        {
            var updateUrlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);

            var error = $"{msg}:{ex.Message}{Environment.NewLine}{ex.StackTrace}";

            string url = $"{updateUrlInfo.Host}/api/LogError/{updateUrlInfo.SystemId}?clientId={Util.GetClientId(localRunInfo.ClientId)}&error={error}";

            Util.SendHttpRequest(url);
        }
コード例 #14
0
        /// <summary>
        /// 启动主程序状态检测
        /// </summary>
        /// <param name="mainAppPath"></param>
        private void StartMainAppStateDetect(string mainAppPath, LocalRunInfo localRunInfo, Config config)
        {
            if (_mainAppStateDetector != null)
            {
                _mainAppStateDetector.Stop();
                _mainAppStateDetector.OnMainAppsClose  -= OnMainAppsClose;
                _mainAppStateDetector.OnCommandRequest -= OnServerCommandRequest;
            }

            _mainAppStateDetector = new MainAppStateDetector(mainAppPath, localRunInfo, config);
            _mainAppStateDetector.OnMainAppsClose  += OnMainAppsClose;
            _mainAppStateDetector.OnCommandRequest += OnServerCommandRequest;
            _mainAppStateDetector.Start();
        }
コード例 #15
0
        private void InputStartApp(LocalRunInfo localRunInfo)
        {
            FrmInput frm = new FrmInput("输入启动程序:", localRunInfo.AppRunCmd);

            if (frm.ShowDialog() == DialogResult.OK)
            {
                localRunInfo.AppRunCmd = frm.Value;
                UpdateHelper.RunMainApp(localRunInfo);
            }
            else
            {
                Exit(localRunInfo);
            }
        }
コード例 #16
0
        private void InputUpdateUrl(LocalRunInfo localRunInfo)
        {
            FrmInput frm = new FrmInput("输入更新地址:", localRunInfo.UpdateUrl);

            if (frm.ShowDialog() == DialogResult.OK)
            {
                localRunInfo.UpdateUrl = frm.Value;
                UpdateHelper.SaveLocalRunInfo(localRunInfo);

                UpdateHelper.Update("正常启动");
            }
            else
            {
                Exit(localRunInfo);
            }
        }
コード例 #17
0
 /// <summary>
 /// 所有主程序关闭事件
 /// </summary>
 /// <param name="detector"></param>
 private void OnMainAppsClose(MainAppStateDetector detector, LocalRunInfo localRunInfo)
 {
     this.Invoke((Action)(() =>
     {
         if (!this._config.KeepUpdaterRunning)
         {
             Exit(null);
         }
         else if (this._config.KeepAppRunning)
         {
             if (!UpdateHelper.IsAppRunning(_mainAppPath))
             {
                 UpdateHelper.RunMainApp(localRunInfo, "由更新程序启动");
             }
         }
     }));
 }
コード例 #18
0
        /// <summary>
        /// 启动更新检测
        /// </summary>
        /// <param name="localRunInfo"></param>
        /// <param name="config"></param>
        private void StartUpdateDetect(LocalRunInfo localRunInfo, Config config)
        {
            if (_updateDetector != null)
            {
                _updateDetector.Stop();
                _updateDetector.OnStart        -= OnUpdateDetectorStart;
                _updateDetector.OnStop         -= OnUpdateDetectorStop;
                _updateDetector.OnNotifyUpdate -= OnUpdateNotification;
            }

            UpdateUrlInfo info = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl);

            _updateDetector                 = new UpdateDetector(config.DetectInterval * 1000, info);
            _updateDetector.OnStart        += OnUpdateDetectorStart;
            _updateDetector.OnStop         += OnUpdateDetectorStop;
            _updateDetector.OnNotifyUpdate += OnUpdateNotification;
            _updateDetector.Start();
        }
コード例 #19
0
        /// <summary>
        /// 运行服务端命令
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="localRunInfo"></param>
        private void OnServerCommandRequest(ClientCommand cmd, LocalRunInfo localRunInfo)
        {
            switch (cmd.Type)
            {
            case ClientCommandType.Start:
                if (!UpdateHelper.IsAppRunning(_mainAppPath))
                {
                    UpdateHelper.RunMainApp(localRunInfo, "由服务端启动");
                }
                break;

            case ClientCommandType.Stop:
                if (UpdateHelper.IsAppRunning(_mainAppPath))
                {
                    UpdateHelper.KillRunningApps(_mainAppPath);
                }
                break;

            default:
                break;
            }
        }
コード例 #20
0
        private void OnUpdateComplete(
            LocalRunInfo localRunInfo,
            IEnumerable <UpdateRunFile> fileDiff,
            List <string> failedUpdateFiles,
            List <string> failedDeleteFiles,
            bool initStart, bool runBat, string msg)
        {
            this.Invoke((Action)(() =>
            {
                _frmProgress.Hide();
                Show();

                OnUpdateStatus("正在保存配置信息...");
                UpdateHelper.SaveLocalRunInfo(localRunInfo);

                if (runBat)
                {
                    OnUpdateStatus("正在做初始化工作...");
                    UpdateHelper.RunBat();
                }

                if (!initStart && fileDiff.Count() > 0)
                { // 由于首次运行的时候更新的文件较多,不写更新日志
                    OnUpdateStatus("正在写更新日志...");
                    LogHelper.WriteUpdateLog(localRunInfo.Ver, fileDiff, failedUpdateFiles, failedDeleteFiles);
                }

                OnUpdateStatus("正在启动主程序...");
                if (string.IsNullOrEmpty(localRunInfo.AppRunCmd))
                {
                    InputStartApp(localRunInfo);
                }
                else
                {
                    UpdateHelper.RunMainApp(localRunInfo, msg);
                }
            }));
        }
コード例 #21
0
 internal static void Exit(LocalRunInfo localRunInfo)
 {
     Environment.Exit(0);
 }
コード例 #22
0
        /// <summary>
        /// 计算文件差异
        /// </summary>
        /// <returns></returns>
        private static IEnumerable <UpdateRunFile> CalcDiff(LocalRunInfo localRunInfo, RemoteRunInfo remoteRunInfo)
        {
            var remoteVer = remoteRunInfo.Ver;

            //if(!string.IsNullOrEmpty(remoteVer) &&
            //    !remoteVer.Equals(localRunInfo.Ver))
            //{ // 为提高效率,只有在版本不同时,才进行文件的差异比较

            var runDir         = Path.GetDirectoryName(Application.ExecutablePath);
            var localRunFiles  = localRunInfo.RunFiles;
            var remoteRunFiles = remoteRunInfo.RunFiles;

            foreach (var rf in remoteRunFiles)
            {
                // 本地不存在或者MD5不同
                var needUpdate = !localRunFiles.TryGetValue(rf.Key, out string localTag) ||
                                 !rf.Value.Equals(localTag) ||
                                 !File.Exists(Path.Combine(runDir, rf.Key));

                if (needUpdate)
                {     // update
                    yield return(new UpdateRunFile
                    {
                        Path = rf.Key,
                        Status = (Constants.RunInfoJsonFile.Equals(rf.Key, StringComparison.OrdinalIgnoreCase) ||
                                  Constants.UpdateLogFile.Equals(rf.Key, StringComparison.OrdinalIgnoreCase)) ?
                                 UpdateRunFileStatus.SkipUpdate : UpdateRunFileStatus.Update,
                        NewTag = rf.Value,
                        OldTag = localTag
                    });
                }
                else
                {
                    yield return(new UpdateRunFile
                    {
                        Path = rf.Key,
                        Status = UpdateRunFileStatus.NotModified,
                        OldTag = localTag,
                    });
                }

                if (localTag != null)
                {
                    localRunFiles.Remove(rf.Key);
                }
            }

            // 剩下的本地文件需要删除
            var thisExeName = Path.GetFileName(Application.ExecutablePath);

            foreach (var lf in localRunFiles)
            {
                yield return(new UpdateRunFile
                {
                    Path = lf.Key,
                    Status = lf.Key.Equals(thisExeName, StringComparison.OrdinalIgnoreCase) ?
                             UpdateRunFileStatus.SkipDelete : UpdateRunFileStatus.Delete,
                    OldTag = lf.Value,
                });
            }
            //}
            //else
            //{
            //    foreach (var lf in localRunInfo.RunFiles)
            //    {
            //        yield return new UpdateRunFile
            //        {
            //            Path = lf.Key,
            //            Status = UpdateRunFileStatus.NotModified,
            //            Tag = lf.Value,
            //        };
            //    }
            //}
        }
コード例 #23
0
        private static void UpdateInternal(string msg)
        {
            LocalRunInfo  localRunInfo  = null;
            UpdateUrlInfo updateUrlInfo = null;

            try
            {
                OnStatus?.Invoke("正在读取本地配置...");
                localRunInfo = GetLocalRunInfo();

                OnStatus?.Invoke("正在验证更新地址...");
                if (string.IsNullOrEmpty(localRunInfo.UpdateUrl))
                {
                    OnNotSpecifyUpdateUrl?.Invoke(localRunInfo); return;
                }

                if ((updateUrlInfo = UpdateUrlInfo.Parse(localRunInfo.UpdateUrl)) == null)
                {
                    OnInvalidUpdateUrl?.Invoke(localRunInfo); return;
                }

                OnStatus?.Invoke("正在读取服务器...");
                var host          = updateUrlInfo.Host;
                var systemId      = updateUrlInfo.SystemId;
                var remoteRunInfo = GetRemoteRunInfo(GetRemoteInfoUrl(host, systemId));

                OnStatus?.Invoke("正在检测差异...");
                var initStart       = (localRunInfo.RunFiles.Count == 0);
                var fileDiffResults = CalcDiff(localRunInfo, remoteRunInfo).ToList();
                var filesToUpdate   = fileDiffResults.Where(f => f.Status == UpdateRunFileStatus.Update || f.Status == UpdateRunFileStatus.Delete).ToList();
                var progress        = 0;
                var total           = filesToUpdate.Count;

                if (total > 0)
                {
                    OnStatus?.Invoke("正在检测运行程序...");
                    if (IsThisAppRunning() ||
                        (!string.IsNullOrEmpty(localRunInfo.AppRunCmd) && IsMainAppRunning(localRunInfo)))
                    {
                        OnMainAppAlreadyRunning?.Invoke(localRunInfo);

                        return;
                    }
                }

                OnStatus?.Invoke("开始更新程序...");
                OnBeginUpdate?.Invoke(localRunInfo);

                var runDir            = Path.GetDirectoryName(Application.ExecutablePath);
                var thisExeName       = Path.GetFileName(Application.ExecutablePath);
                var runBat            = false;
                var runFileResults    = new DicIgnoreCase <string>();
                var failedUpdateFiles = new List <string>();
                var failedDeleteFiles = new List <string>();

                foreach (var file in filesToUpdate)
                {
                    if (Constants.BatFile.Equals(file.Path, StringComparison.OrdinalIgnoreCase))
                    {
                        runBat = true;
                    }

                    if (file.Status == UpdateRunFileStatus.Update)
                    {
                        var url        = GetRunFileUrl(host, systemId, file.Path);
                        var localPath  = Path.Combine(runDir, file.Path);
                        var updateSelf = file.Path.Equals(thisExeName, StringComparison.OrdinalIgnoreCase); // 自更新

                        OnProcessFile?.Invoke("正在安装文件:" + localPath);
                        var success = DownloadRunFile(url, localPath, possibllyInUse: updateSelf);

                        if (!success)
                        {
                            failedUpdateFiles.Add(file.Path);

                            // 对于更新失败的文件(非新增),新的配置文件应该仍包含更新前的文件标识
                            if (!string.IsNullOrEmpty(file.OldTag))
                            {
                                runFileResults.Add(file.Path, file.OldTag);
                            }
                        }
                        else
                        {
                            runFileResults.Add(file.Path, file.NewTag);
                        }
                    }
                    else if (file.Status == UpdateRunFileStatus.Delete)
                    { // 删除文件
                        var localPath = Path.Combine(runDir, file.Path);

                        OnProcessFile?.Invoke("正在删除文件:" + localPath);
                        if (!DeleteRunFile(localPath))
                        {
                            failedDeleteFiles.Add(file.Path);

                            // 对于删除失败的文件,新的配置文件应该仍包含旧的文件标识
                            runFileResults.Add(file.Path, file.OldTag);
                        }
                    }

                    OnProgress?.Invoke((++progress) * 1.0 / total);
                }

                foreach (var f in fileDiffResults.Where(f => f.Status == UpdateRunFileStatus.NotModified))
                {
                    runFileResults.Add(f.Path, f.OldTag);
                }

                localRunInfo.Ver      = remoteRunInfo.Ver;
                localRunInfo.RunFiles = runFileResults;

                OnComplete?.Invoke(localRunInfo, fileDiffResults, failedUpdateFiles, failedDeleteFiles, initStart, runBat, msg);
            }
            catch (Exception ex)
            {
                if (localRunInfo != null)
                {
                    LogHelper.LogErrorToServer($"客户端更新失败({msg})", ex, localRunInfo);
                }

                OnError?.Invoke(localRunInfo, ex);
            }
        }