示例#1
0
        async Task ProcessStart(string strExePath)
        {
            ShowSplashWindow();

            // 先删除启动状态文件
            string stateFileName = Path.Combine(_binDir, "dp2ssl_started");

            try
            {
                File.Delete(stateFileName);
            }
            catch
            {
            }

            string arguments = "";

            if (IsSilently())
            {
                arguments = "silently";
            }

            GreenInstaller.WriteInfoLog($"启动 path='{strExePath}', arguments='{arguments}'");

            var proc = Process.Start(strExePath, arguments);

            // 等待 dp2ssl 创建启动状态文件
            if (_splashForm != null)
            {
                DateTime begin_time = DateTime.Now;
                while (File.Exists(stateFileName) == false)
                {
                    await Task.Delay(100);

                    // 等待最多一分钟
                    if (DateTime.Now - begin_time > TimeSpan.FromSeconds(60))
                    {
                        break;
                    }
                }

                // 最少要等待 5 秒
                TimeSpan length = TimeSpan.FromSeconds(5);
                if (DateTime.Now - begin_time < length)
                {
                    this.Invoke((Action)(() =>
                    {
                        this.Location = new Point(-1000, -1000);
                        _splashForm.Activate();
                    }));
                    await Task.Delay(length - (DateTime.Now - begin_time));
                }
            }

            // 等待 dp2ssl 主窗口创建,然后 greensetup.exe 才退出
            Application.Exit();
        }
示例#2
0
        // TODO: 是否在延时一段以后自动关闭?
        void ErrorBox(string message)
        {
            GreenInstaller.WriteInfoLog(message);

            this.Invoke((Action)(() =>
            {
                MessageBox.Show(this, message);
            }));
        }
示例#3
0
        private void MainForm_Load(object sender, EventArgs e)
        {
            InitialLogging();

            GreenInstaller.WriteInfoLog($"**********");
            GreenInstaller.WriteInfoLog($"greensetup 开始执行");

            string args = string.Join(' ', Environment.GetCommandLineArgs());

            GreenInstaller.WriteInfoLog($"命令行参数: {args}");

            _ = Start(IsCmdLineUpdate() ? false : true);
        }
示例#4
0
        void ProcessStart(string strExePath)
        {
            string arguments = "";

            if (IsSilently())
            {
                arguments = "silently";
            }

            GreenInstaller.WriteInfoLog($"启动 path='{strExePath}', arguments='{arguments}'");

            Process.Start(strExePath, arguments);
            Application.Exit();
        }
示例#5
0
        private void button_createShortcut_Click(object sender, EventArgs e)
        {
            // 创建桌面快捷方式
            GreenInstaller.CreateShortcut(
                "desktop",
                "dp2SSL 自助借还(绿色)",
                "dp2SSL 自助借还(绿色)",
                "c:\\dp2ssl\\dp2ssl.exe");

            /*
             * GreenInstaller.CreateShortcutToStartMenu(
             * "dp2ssl 绿色",
             * "c:\\dp2ssl\\dp2ssl.exe",
             * true);
             */
        }
示例#6
0
 private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
 {
     GreenInstaller.WriteInfoLog($"greensetup 关闭退出");
 }
示例#7
0
        // 启动 dp2ssl.exe;或首次安装;或升级并启动 dp2ssl.exe
        // parameters:
        //      delayUpdate 是否让 dp2ssl.exe 启动起来再探测升级?
        //                  意思就是,== true,让 dp2ssl.exe 去负责升级,而 greensetup.exe 这里不负责下载升级(只负责展开下载好的 .zip)。这样的特点是启动速度快
        //                  == false,让 greensetup.exe 直接探测下载升级,缺点是 dp2ssl.exe 启动就晚一点
        //                  但首次安装的时候,则是 greensetup.exe 负责下载 .zip 文件并安装。因为此时 dp2ssl.exe 还并不存在
        async Task Start(bool delayUpdate)
        {
            // *** 检查 dp2ssl.exe 是否已经在运行
            if (GreenInstaller.HasModuleStarted("{75BAF3F0-FF7F-46BB-9ACD-8FE7429BF291}") == true)
            {
                ErrorBox("dp2SSL 已经启动了,无法重复启动");
                Application.Exit();
                return;
            }

            // testing
            // await Task.Delay(5000);

            // 延时 30 秒,避免上一个 dp2ssl.exe 尚未彻底退出。如果没有彻底退出,会导致本次展开 .zip 文件时候覆盖失败
            if (IsDelay())
            {
                // TODO: 出现 Splash 窗口或者文字提示请等待
                var old_style = this.progressBar1.Style;
                this.Invoke(new Action(() =>
                {
                    this.progressBar1.Style = ProgressBarStyle.Marquee;
                    this.label_message.Text = "请等待 ...";
                }));

                try
                {
                    // TODO: 可以改进为不断观察,等到另一个 dp2ssl.exe 如果退出则结束等待
                    await Task.Delay(TimeSpan.FromSeconds(30));
                }
                finally
                {
                    this.Invoke(new Action(() =>
                    {
                        this.progressBar1.Style = old_style;
                    }));
                }
            }

            string strExePath   = Path.Combine(_binDir, "dp2ssl.exe");
            bool   firstInstall = File.Exists(strExePath) == false;

            // *** 检查状态文件
            // result.Value
            //      -1  出错
            //      0   不存在状态文件
            //      1   正在下载 .zip 过程中。.zip 不完整
            //      2   当前 .zip 和 .exe 已经一样新
            //      3   当前 .zip 比 .exe 要新。需要展开 .zip 进行更新安装
            //      4   下载 .zip 失败。.zip 不完整
            //      5   当前 .zip 比 .exe 要新,需要重启计算机以便展开的文件生效
            var check_result = GreenInstaller.CheckStateFile(_binDir);

            GreenInstaller.WriteInfoLog($"检查状态文件。check_result:{check_result.ToString()}");

            // 展开,并启动 dp2ssl.exe
            if (check_result.Value == 3 ||
                check_result.Value == 0)    // 2020/9/11 增加
            {
                GreenInstaller.WriteInfoLog($"将此前已经下载的 .zip 文件,展开,并立即启动 dp2ssl.exe");

                // return:
                //      -1  出错
                //      0   成功。不需要 reboot
                //      2   成功,但需要立即重新启动计算机才能让复制的文件生效
                var extract_result = GreenInstaller.ExtractFiles(_binDir);

                GreenInstaller.WriteInfoLog($"展开文件。extract_result:{extract_result.ToString()}");

                if (extract_result.Value == -1)
                {
                    if (extract_result.ErrorCode == "sourceFileNotFound")
                    {
                        GreenInstaller.WriteInfoLog($"{extract_result.ErrorInfo}, 所以改为进行首次安装");
                        goto FIRST_INSTALL;
                    }
                    ErrorBox(extract_result.ErrorInfo);
                    return;
                }
                else if (extract_result.Value == 2)
                {
                    // 2020/9/11
                    GreenInstaller.WriteInfoLog($"展开过程中发现部分文件被锁定了无法覆盖,已经被写入特殊文件,需要等下次 Windows 重启以后才能生效。本次依然用当前可执行文件启动 dp2ssl.exe");
                    // ErrorBox("部分文件更新受阻,请立即重新启动 Windows");

                    // TODO: 需要有个命令行参数,让 dp2ssl.exe 启动起来后明显提示用户看到信息和状态,需要重启 Windows
                }
                await ProcessStart(strExePath);

                return;
            }

            /*
             * if (check_result.Value == 1
             || check_result.Value == 5)
             ||{
             || ErrorBox(check_result.ErrorInfo);
             || Application.Exit();
             || return;
             ||}
             */

            /*
             * Debugger.Launch();
             *
             * // 拷贝 greensetup.exe
             * string exePath = Assembly.GetExecutingAssembly().Location.ToLower();
             * string targetExePath = Path.Combine(_binDir, "greensetup.exe");
             * if (exePath.EndsWith("greensetup.exe")
             *  && File.Exists(targetExePath) == false
             *  && exePath.ToLower() != targetExePath.ToLower())
             * {
             *  MessageBox.Show(this, "copy greensetup.exe");
             *  Library.TryCreateDir(_binDir);
             *  File.Copy(exePath, targetExePath, true);
             * }
             * else
             *  MessageBox.Show(this, "not copy greensetup.exe");
             */

            if (firstInstall == false && delayUpdate)
            {
                GreenInstaller.WriteInfoLog($"非首次安装情形。立即启动 dp2ssl.exe");

                await ProcessStart(strExePath);

                return;
            }

FIRST_INSTALL:          // 第一次安装

            string style = "updateGreenSetupExe,debugInfo";

            if (delayUpdate == false)
            {
                style += ",clearStateFile";
            }
            if (firstInstall)
            {
                style += ",mustExpandZip";  // 无论是否有更新,都要展开两个 .zip 文件。因为 dp2ssl.exe 不存在,必须要展开 .zip 才能得到
            }
            GreenInstaller.WriteInfoLog($"style={style}");

            // *** 从 Web 升级
            double ratio = 1;
            // 从 Web 服务器安装或者升级绿色版
            // result.Value:
            //      -1  出错
            //      0   经过检查发现没有必要升级
            //      1   成功
            //      2   成功,但需要立即重新启动计算机才能让复制的文件生效
            var result = await GreenInstaller.InstallFromWeb(GreenInstaller.dp2ssl_weburl,
                                                             _binDir,
                                                             style,
                                                             //false,
                                                             //true,
                                                             _cancel.Token,
                                                             (double min, double max, double value, string text) =>
            {
                try
                {
                    this.Invoke(new Action(() =>
                    {
                        if (text != null)
                        {
                            label_message.Text = text;
                        }
                        if (min != -1)
                        {
                            progressBar1.Minimum = (Int32)min;
                        }
                        if (max != -1)
                        {
                            if (max <= Int32.MaxValue)
                            {
                                ratio = 1;
                                progressBar1.Maximum = (Int32)max;
                            }
                            else
                            {
                                ratio = Int32.MaxValue / max;
                                progressBar1.Maximum = Int32.MaxValue;
                            }
                        }
                        if (value != -1)
                        {
                            progressBar1.Value = (int)((double)value * ratio);
                        }
                    }));
                }
                catch
                {
                }
            });

            GreenInstaller.WriteInfoLog($"InstallFromWeb() 返回: \r\n{result.ToString()}");

            if (result.Value == -1)
            {
                if (result.ErrorCode == "System.Net.WebException")
                {
                    if (File.Exists(strExePath))
                    {
                        await ProcessStart(strExePath);

                        return;
                    }
                }
                ErrorBox(result.ErrorInfo);
                Application.Exit();
                return;
            }

            // result.Value == 2 要提醒重启 Windows 以完成安装
            if (result.Value == 2)
            {
                ErrorBox(result.ErrorInfo);
            }

            // TODO: 从 dp2ssl.exe 中取信息?

            // 首次安装成功
            if (firstInstall)
            {
                GreenInstaller.WriteInfoLog($"首次安装成功");

                // 创建桌面快捷方式
                GreenInstaller.CreateShortcut(
                    "desktop",
                    "dp2SSL 自助借还(绿色)",
                    "dp2SSL 自助借还(绿色)",
                    Path.Combine(_binDir, "greensetup.exe"));   // "dp2ssl.exe"

                GreenInstaller.CreateShortcut(
                    "startup",
                    "dp2SSL 自助借还(绿色)",
                    "dp2SSL 自助借还(绿色)",
                    Path.Combine(_binDir, "greensetup.exe")); // "dp2ssl.exe"

                // 迁移用户文件夹
                string sourceDirectory = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                    "dp2ssl");

                /*
                 * if (Directory.Exists(sourceDirectory))
                 * {
                 *  string targetDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "dp2\\dp2ssl");
                 *  if (Directory.Exists(targetDirectory) == false)
                 *  {
                 *      var move_result = GreenInstaller.MoveUserDirectory(sourceDirectory,
                 *          targetDirectory,
                 *          _binDir,
                 *          "maskSource");
                 *      GreenInstaller.WriteInfoLog($"迁移用户文件夹 sourceDirectory={sourceDirectory}, targetDirectory={targetDirectory}, move_result={move_result.ToString()}");
                 *  }
                 *  else
                 *  {
                 *      GreenInstaller.WriteInfoLog($"绿色版用户文件夹 targetDirectory={targetDirectory} 已经存在,不再重复进行迁移");
                 *  }
                 * }
                 */
                string targetDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "dp2\\dp2ssl");
                {
                    var move_result = GreenInstaller.MoveUserDirectory(sourceDirectory,
                                                                       targetDirectory,
                                                                       _binDir,
                                                                       "maskSource");
                    GreenInstaller.WriteInfoLog($"迁移用户文件夹 sourceDirectory={sourceDirectory}, targetDirectory={targetDirectory}, move_result={move_result.ToString()}");
                }
            }

            await ProcessStart(strExePath);

            return;
        }
示例#8
0
        string ProcessRestart(string command)
        {
            // 子参数
            string param = command.Substring("restart".Length).Trim().ToLower();

            if ( // string.IsNullOrEmpty(param)
                param == "computer")
            {
                // 重启电脑
                Task.Run(async() =>
                {
                    try
                    {
                        // 为 dp2ssl 开机后自动重启预先设定好 cmdlineparam.txt 文件
                        WriteParameterFile();

                        await Task.Delay(1000);
                        // https://stackoverflow.com/questions/4286354/restart-computer-from-winforms-app
                        ProcessStartInfo proc = new ProcessStartInfo();
                        proc.WindowStyle      = ProcessWindowStyle.Hidden;
                        proc.FileName         = "cmd";
                        proc.Arguments        = "/C shutdown -f -r";
                        Process.Start(proc);
                    }
                    catch
                    {
                    }
                });
                return("服务器将在一秒后重新启动");
            }
            if (param != null && param.StartsWith("dp2ssl"))
            {
                // 子参数。默认 silently
                bool silently = true;
                {
                    string arg = param.Substring("dp2ssl".Length).Trim();
                    if (arg != null && arg.StartsWith("interact"))
                    {
                        silently = false;
                    }
                }

                // 重启 dp2ssl
                ExitProcess("dp2SSL", false);
                Thread.Sleep(5000);
                if (HasModuleStarted(MutexName) == true)
                {
                    ExitProcess("dp2SSL", true);
                }

                try
                {
                    // 启动
                    // StartModule(ShortcutPath, "");
                    // Process.Start("c:\\dp2ssl\\dp2ssl.exe");
                    string exe_path1 = "c:\\dp2ssl\\greensetup.exe";
                    string exe_path2 = "c:\\dp2ssl\\dp2ssl.exe";
                    if (File.Exists(exe_path1))
                    {
                        // 注意命令行参数第一个字符应该是空格
                        ProcessExtensions.StartProcessAsCurrentUser(exe_path1,
                                                                    silently ? " silently" : "");
                    }
                    else if (File.Exists(exe_path2))
                    {
                        // 启动之前,检查 .zip 是否已经展开
                        {
                            string binDir = "c:\\dp2ssl";
                            // *** 检查状态文件
                            // result.Value
                            //      -1  出错
                            //      0   不存在状态文件
                            //      1   正在下载 .zip 过程中。.zip 不完整
                            //      2   当前 .zip 和 .exe 已经一样新
                            //      3   当前 .zip 比 .exe 要新。需要展开 .zip 进行更新安装
                            //      4   下载 .zip 失败。.zip 不完整
                            //      5   当前 .zip 比 .exe 要新,需要重启计算机以便展开的文件生效
                            var check_result = GreenInstaller.CheckStateFile(binDir);
                            // 展开
                            if (check_result.Value == 3)
                            {
                                var extract_result = GreenInstaller.ExtractFiles(binDir);
                                if (extract_result.Value == -1)
                                {
                                    // TODO: 写入错误日志
                                    WriteErrorLog($"展开压缩文件时出错: {extract_result.ErrorInfo}");
                                }
                            }
                        }

                        // 注意命令行参数第一个字符应该是空格
                        ProcessExtensions.StartProcessAsCurrentUser(exe_path2,
                                                                    silently ? " silently" : "");
                    }
                    else
                    {
                        return($"{exe_path1} 和 {exe_path2} 均未找到,无法启动");
                    }
                    return("dp2SSL 已经重新启动");
                }
                catch (Exception ex)
                {
                    return($"启动过程出现异常: {ExceptionUtil.GetDebugText(ex)}");
                }
            }

            return($"命令 '{command}' 未知的子参数 '{param}'");
        }
示例#9
0
        // 启动一般监控任务
        public static void StartMonitorTask()
        {
            if (_monitorTask != null)
            {
                return;
            }

            CancellationToken token = _cancel.Token;
            bool download_complete  = false;

            token.Register(() =>
            {
                _eventMonitor.Set();
            });

            _monitorTask = Task.Factory.StartNew(async() =>
            {
                WpfClientInfo.WriteInfoLog("监控专用线程开始");
                try
                {
                    while (token.IsCancellationRequested == false)
                    {
                        // await Task.Delay(TimeSpan.FromSeconds(10));
                        _eventMonitor.WaitOne(_monitorIdleLength);

                        token.ThrowIfCancellationRequested();

                        // ***
                        // 关闭天线射频
                        if (_tagAdded)
                        {
                            _ = Task.Run(async() =>
                            {
                                try
                                {
                                    await SelectAntennaAsync();
                                }
                                catch (Exception ex)
                                {
                                    WpfClientInfo.WriteErrorLog($"关闭天线射频 SelectAntennaAsync() 时出现异常: {ExceptionUtil.GetDebugText(ex)}");
                                }
                            });
                            _tagAdded = false;
                        }

                        if (DateTime.Now - _lastDetectTime > _detectPeriod)
                        {
                            DetectLibraryNetwork();

                            _lastDetectTime = DateTime.Now;
                        }

                        // 提醒关门
                        WarningCloseDoor();

                        // 下载或同步读者信息
                        string startDate = LoadStartDate();
                        if (/*download_complete == false || */
                            string.IsNullOrEmpty(startDate))
                        {
                            // 如果 Config 中没有记载断点位置,说明以前从来没有首次同步过。需要进行一次首次同步
                            if (string.IsNullOrEmpty(startDate))
                            {
                                // SaveStartDate("");

                                var repl_result = await PatronReplication.DownloadAllPatronRecordAsync(token);
                                if (repl_result.Value == -1)
                                {
                                    // TODO: 判断通讯出错的错误码。如果是通讯出错,则稍后需要重试下载
                                }
                                else
                                {
                                    SaveStartDate(repl_result.StartDate);
                                }

                                // 立刻允许接着做一次零星同步
                                ActivateMonitor();
                            }
                            // download_complete = true;
                        }
                        else
                        {
                            // 进行零星同步
                            if (DateTime.Now - _lastReplicateTime > _replicatePeriod)
                            {
                                // string startDate = LoadStartDate();

                                // testing
                                // startDate = "20200507:0-";

                                if (string.IsNullOrEmpty(startDate) == false)
                                {
                                    string endDate = DateTimeUtil.DateTimeToString8(DateTime.Now);

                                    // parameters:
                                    //      strLastDate   处理中断或者结束时返回最后处理过的日期
                                    //      last_index  处理或中断返回时最后处理过的位置。以后继续处理的时候可以从这个偏移开始
                                    // return:
                                    //      -1  出错
                                    //      0   中断
                                    //      1   完成
                                    ReplicationResult repl_result = PatronReplication.DoReplication(
                                        startDate,
                                        endDate,
                                        LogType.OperLog,
                                        token);
                                    if (repl_result.Value == -1)
                                    {
                                        WpfClientInfo.WriteErrorLog($"同步出错: {repl_result.ErrorInfo}");
                                    }
                                    else if (repl_result.Value == 1)
                                    {
                                        string lastDate = repl_result.LastDate + ":" + repl_result.LastIndex + "-";    // 注意 - 符号不能少。少了意思就会变成每次只获取一条日志记录了
                                        SaveStartDate(lastDate);
                                    }

                                    _lastReplicateTime = DateTime.Now;
                                }
                            }
                        }

                        // 检查升级 dp2ssl
                        if (_updated == false
                            // && StringUtil.IsDevelopMode() == false
                            && ApplicationDeployment.IsNetworkDeployed == false &&
                            DateTime.Now - _lastUpdateTime > _updatePeriod)
                        {
                            WpfClientInfo.WriteInfoLog("开始自动检查升级");
                            // result.Value:
                            //      -1  出错
                            //      0   经过检查发现没有必要升级
                            //      1   成功
                            //      2   成功,但需要立即重新启动计算机才能让复制的文件生效
                            var update_result = await GreenInstaller.InstallFromWeb("http://dp2003.com/dp2ssl/v1_dev",
                                                                                    "c:\\dp2ssl",
                                                                                    "delayExtract,updateGreenSetupExe",
                                                                                    //true,
                                                                                    //true,
                                                                                    token,
                                                                                    null);
                            if (update_result.Value == -1)
                            {
                                WpfClientInfo.WriteErrorLog($"自动检查升级出错: {update_result.ErrorInfo}");
                            }
                            else
                            {
                                WpfClientInfo.WriteInfoLog($"结束自动检查升级 update_result:{update_result.ToString()}");
                            }

                            if (update_result.Value == 1 || update_result.Value == 2)
                            {
                                App.TriggerUpdated("重启可使用新版本");
                                _updated = true;
                                PageShelf.TrySetMessage(null, "dp2SSL 升级文件已经下载成功,下次重启时可自动升级到新版本");
                            }
                            _lastUpdateTime = DateTime.Now;
                        }
                    }
                    _monitorTask = null;
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception ex)
                {
                    WpfClientInfo.WriteErrorLog($"监控专用线程出现异常: {ExceptionUtil.GetDebugText(ex)}");
                    App.SetError("monitor", $"监控专用线程出现异常: {ex.Message}");
                }
                finally
                {
                    WpfClientInfo.WriteInfoLog("监控专用线程结束");
                }
            },
                                                 token,
                                                 TaskCreationOptions.LongRunning,
                                                 TaskScheduler.Default);
        }
示例#10
0
        async Task install()
        {
            /*
             * string exePath = Assembly.GetExecutingAssembly().Location;
             * bool updateGreenSetupExe = exePath.ToLower() != "c:\\dp2ssl\\greensetup.exe";
             */

            double ratio  = 1;
            var    result = await GreenInstaller.InstallFromWeb("http://dp2003.com/dp2ssl/v1_dev",
                                                                "c:\\dp2ssl",
// null,
                                                                false,
                                                                true,
                                                                _cancel.Token,
                                                                (double min, double max, double value, string text) =>
            {
                this.Invoke(new Action(() =>
                {
                    if (text != null)
                    {
                        label_message.Text = text;
                    }
                    if (min != -1)
                    {
                        progressBar1.Minimum = (Int32)min;
                    }
                    if (max != -1)
                    {
                        if (max <= Int32.MaxValue)
                        {
                            ratio = 1;
                            progressBar1.Maximum = (Int32)max;
                        }
                        else
                        {
                            ratio = Int32.MaxValue / max;
                            progressBar1.Maximum = Int32.MaxValue;
                        }
                    }
                    if (value != -1)
                    {
                        progressBar1.Value = (int)((double)value * ratio);
                    }
                }));
            });

            if (result.Value == -1)
            {
                MessageBox.Show(this, result.ErrorInfo);
                return;
            }

            // TODO: 从 dp2ssl.exe 中取信息?

            // 创建桌面快捷方式
            GreenInstaller.CreateShortcut(
                "desktop",
                "dp2SSL 自助借还(绿色)",
                "dp2SSL 自助借还(绿色)",
                "c:\\dp2ssl\\dp2ssl.exe");

            // 迁移用户文件夹
            string sourceDirectory = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                "dp2ssl");

            if (Directory.Exists(sourceDirectory))
            {
                string targetDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "dp2\\dp2ssl");
                var    move_result     = GreenInstaller.MoveUserDirectory(sourceDirectory,
                                                                          targetDirectory,
                                                                          "c:\\dp2ssl",
                                                                          "maskSource");
            }
            return;
        }
示例#11
0
        // 启动 dp2ssl.exe;或首次安装;或升级并启动 dp2ssl.exe
        // parameters:
        //      delayUpdate 是否让 dp2ssl.exe 启动起来再探测升级?
        //                  意思就是,== true,让 dp2ssl.exe 去负责升级,而 greensetup.exe 这里不负责下载升级(只负责展开下载好的 .zip)。这样的特点是启动速度快
        //                  == false,让 greensetup.exe 直接探测下载升级,缺点是 dp2ssl.exe 启动就晚一点
        //                  但首次安装的时候,则是 greensetup.exe 负责下载 .zip 文件并安装。因为此时 dp2ssl.exe 还并不存在
        async Task Start(bool delayUpdate)
        {
            // *** 检查 dp2ssl.exe 是否已经在运行
            if (GreenInstaller.HasModuleStarted("{75BAF3F0-FF7F-46BB-9ACD-8FE7429BF291}") == true)
            {
                ErrorBox("dp2SSL 已经启动了,无法重复启动");
                Application.Exit();
                return;
            }

            string strExePath   = Path.Combine(_binDir, "dp2ssl.exe");
            bool   firstInstall = File.Exists(strExePath) == false;

            // *** 检查状态文件
            // result.Value
            //      -1  出错
            //      0   不存在状态文件
            //      1   正在下载 .zip 过程中。.zip 不完整
            //      2   当前 .zip 和 .exe 已经一样新
            //      3   当前 .zip 比 .exe 要新。需要展开 .zip 进行更新安装
            //      4   下载 .zip 失败。.zip 不完整
            //      5   当前 .zip 比 .exe 要新,需要重启计算机以便展开的文件生效
            var check_result = GreenInstaller.CheckStateFile(_binDir);

            GreenInstaller.WriteInfoLog($"检查状态文件。check_result:{check_result.ToString()}");

            // 展开,并启动 dp2ssl.exe
            if (check_result.Value == 3)
            {
                GreenInstaller.WriteInfoLog($"以前遗留的 .zip 文件,展开,并立即启动 dp2ssl.exe");

                var extract_result = GreenInstaller.ExtractFiles(_binDir);
                if (extract_result.Value == -1)
                {
                    ErrorBox(extract_result.ErrorInfo);
                    return;
                }
                ProcessStart(strExePath);
                return;
            }

            /*
             * if (check_result.Value == 1
             || check_result.Value == 5)
             ||{
             || ErrorBox(check_result.ErrorInfo);
             || Application.Exit();
             || return;
             ||}
             */

            /*
             * Debugger.Launch();
             *
             * // 拷贝 greensetup.exe
             * string exePath = Assembly.GetExecutingAssembly().Location.ToLower();
             * string targetExePath = Path.Combine(_binDir, "greensetup.exe");
             * if (exePath.EndsWith("greensetup.exe")
             *  && File.Exists(targetExePath) == false
             *  && exePath.ToLower() != targetExePath.ToLower())
             * {
             *  MessageBox.Show(this, "copy greensetup.exe");
             *  Library.TryCreateDir(_binDir);
             *  File.Copy(exePath, targetExePath, true);
             * }
             * else
             *  MessageBox.Show(this, "not copy greensetup.exe");
             */

            if (firstInstall == false && delayUpdate)
            {
                GreenInstaller.WriteInfoLog($"非首次安装情形。立即启动 dp2ssl.exe");

                ProcessStart(strExePath);
                return;
            }

            string style = "updateGreenSetupExe";

            if (delayUpdate == false)
            {
                style += ",clearStateFile";
            }

            GreenInstaller.WriteInfoLog($"style={style}");

            // *** 从 Web 升级
            double ratio = 1;
            // 从 Web 服务器安装或者升级绿色版
            // result.Value:
            //      -1  出错
            //      0   经过检查发现没有必要升级
            //      1   成功
            //      2   成功,但需要立即重新启动计算机才能让复制的文件生效
            var result = await GreenInstaller.InstallFromWeb("http://dp2003.com/dp2ssl/v1_dev",
                                                             _binDir,
                                                             style,
                                                             //false,
                                                             //true,
                                                             _cancel.Token,
                                                             (double min, double max, double value, string text) =>
            {
                this.Invoke(new Action(() =>
                {
                    if (text != null)
                    {
                        label_message.Text = text;
                    }
                    if (min != -1)
                    {
                        progressBar1.Minimum = (Int32)min;
                    }
                    if (max != -1)
                    {
                        if (max <= Int32.MaxValue)
                        {
                            ratio = 1;
                            progressBar1.Maximum = (Int32)max;
                        }
                        else
                        {
                            ratio = Int32.MaxValue / max;
                            progressBar1.Maximum = Int32.MaxValue;
                        }
                    }
                    if (value != -1)
                    {
                        progressBar1.Value = (int)((double)value * ratio);
                    }
                }));
            });

            if (result.Value == -1)
            {
                if (result.ErrorCode == "System.Net.WebException")
                {
                    if (File.Exists(strExePath))
                    {
                        ProcessStart(strExePath);
                        return;
                    }
                }
                ErrorBox(result.ErrorInfo);
                Application.Exit();
                return;
            }

            // TODO: 从 dp2ssl.exe 中取信息?

            // 首次安装成功
            if (firstInstall)
            {
                GreenInstaller.WriteInfoLog($"首次安装成功");

                // 创建桌面快捷方式
                GreenInstaller.CreateShortcut(
                    "desktop",
                    "dp2SSL 自助借还(绿色)",
                    "dp2SSL 自助借还(绿色)",
                    Path.Combine(_binDir, "greensetup.exe"));   // "dp2ssl.exe"

                GreenInstaller.CreateShortcut(
                    "startup",
                    "dp2SSL 自助借还(绿色)",
                    "dp2SSL 自助借还(绿色)",
                    Path.Combine(_binDir, "greensetup.exe")); // "dp2ssl.exe"

                // 迁移用户文件夹
                string sourceDirectory = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                    "dp2ssl");
                if (Directory.Exists(sourceDirectory))
                {
                    string targetDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "dp2\\dp2ssl");
                    var    move_result     = GreenInstaller.MoveUserDirectory(sourceDirectory,
                                                                              targetDirectory,
                                                                              _binDir,
                                                                              "maskSource");
                    GreenInstaller.WriteInfoLog($"迁移用户文件夹 sourceDirectory={sourceDirectory}, targetDirectory={targetDirectory}, move_result={move_result.ToString()}");
                }
            }

            ProcessStart(strExePath);
            return;
        }