Example #1
0
        /*
         * // 软件安装包下载路径。例如 http://dp2003.com/dp2ssl/v1
         * public string DownloadUrl { get; set; }
         *
         * // 安装目标路径。例如 c:\dp2ssl
         * public string InstallDirectory { get; set; }
         *
         * // 用户目录。例如 c:\ProgramData\dp2\dp2ssl 或 c:\Users\xietao\dp2ssl
         * // 如果为空,则默认 当前 Windows 用户的用户目录的 xxxx 子目录 (xxxx 为产品名,例如 dp2ssl 或者 dp2circulation_v2 之类)
         * public string UserDirectory { get; set; }
         */

        // 迁移用户文件夹
        // parameters:
        //      sourceDirectory 即将被移动的旧位置用户文件夹
        //      targetDirectory 要移动到的新目标位置用户文件夹
        //      binDirectory    可执行文件夹。要在里面创建一个 userDirectory.txt 文件,标注目标文件夹位置。如果本参数为 null,表示不创建这个文件
        //      style   风格。maskSource 表示会在旧位置用户文件夹里面创建一个 userDirectoryMask.txt 文件,表示此文件夹已经被废弃
        public static NormalResult MoveUserDirectory(string sourceDirectory,
                                                     string targetDirectory,
                                                     string binDirectory,
                                                     string style)
        {
            int nRet = Library.CopyDirectory(sourceDirectory,
                                             targetDirectory,
                                             null,
                                             false,
                                             out string strError);

            if (nRet == -1)
            {
                return new NormalResult
                       {
                           Value     = -1,
                           ErrorInfo = $"CopyDirectory() 出错: {strError}"
                       }
            }
            ;

            // 2020/6/10
            // 将 targetDirectory 中的 userDirectory.txt 文件删除
            {
                string filename = Path.Combine(targetDirectory, "userDirectoryMask.txt");

                File.Delete(filename);
            }

            // 在源目录中做出标记,以便以后用到这个目录的程序会警告退出
            if (StringUtil0.IsInList("maskSource", style))
            {
                string strMaskFileName = Path.Combine(sourceDirectory, "userDirectoryMask.txt");
                File.WriteAllText(strMaskFileName, $"removed:此用户文件夹已经被移动到 {targetDirectory}");
            }

            // 在可执行文件目录中标记用户目录位置
            if (binDirectory != null)
            {
                var set_result = SetUserDirectory(binDirectory, targetDirectory);
                if (set_result.Value == -1)
                {
                    return(set_result);
                }
            }

            return(new NormalResult());
        }
Example #2
0
        public static NormalResult ExtractFiles(string strBinDir)
        {
            List <string> filenames = new List <string>()
            {
                "app.zip",
                "data.zip"
            };

            {
                // setProgress?.Invoke(-1, -1, -1, "正在解压文件");

                // TODO: 直接解压到目标位置即可
                string files = StringUtil0.MakePathList(filenames);
                // 安装软件。用 MoveFileEx 法
                // return:
                //      -1  出错
                //      0   成功。不需要 reboot
                //      1   成功。需要 reboot
                int nRet = Install_2(strBinDir,
                                     strBinDir,
                                     files,
                                     Path.GetTempPath(),
                                     out string strError);
                if (nRet == -1)
                {
                    // TODO: 这里是否需要删除两个 .zip 文件以便迫使后面重新下载和展开?
                    return(new NormalResult
                    {
                        Value = -1,
                        ErrorInfo = strError
                    });
                }
                if (nRet == 1)
                {
                    WriteStateFile(strBinDir, "waitingReboot");

                    return(new NormalResult
                    {
                        Value = 2   // 表示需要重启计算机
                    });
                }
                WriteStateFile(strBinDir, "installed");
            }

            return(new NormalResult());
        }
Example #3
0
        // 启动绿色安装小工具。因为 dp2circulation 正在运行时无法覆盖替换文件,所以需要另外启动一个小程序来完成这个任务
        public static int StartGreenUtility(List <string> _updatedGreenZipFileNames,
                                            string strBinDir,
                                            string waitExe)
        {
            if (_updatedGreenZipFileNames.Count == 0)
            {
                throw new ArgumentException("调用 StartGreenUtility() 前应该准备好 _updatedGreenZipFileNames 内容");
            }

            // string strBinDir = GetBinDir();
            string strUtilDir = GetUtilDir(strBinDir);

            string strExePath    = Path.Combine(strUtilDir, "greenutility.exe");
            string strParameters = "-silence -action:install -source:"
                                   + strBinDir                                                  // source 是指存储了 .zip 文件的目录
                                   + " -target:" + strBinDir                                    // target 是指最终要安装的目录
                                   + (string.IsNullOrEmpty(waitExe) ? "" : $" -wait:{waitExe}") // " -wait:dp2circulation.exe"
                                   + " -files:" + StringUtil0.MakePathList(_updatedGreenZipFileNames);

            try
            {
                var process = System.Diagnostics.Process.Start(strExePath, strParameters);
                process.WaitForExit();
                return(process.ExitCode);
            }
            catch (Win32Exception ex)
            {
                // 改为抛出包含 Win32 错误码的异常
                // https://msdn.microsoft.com/en-us/library/ms681382(v=vs.85).aspx
                // ERROR_ACCESS_DENIED
                // 5 (0x5)
                // Access is denied.
                int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
                throw new Exception("GetLastWin32Error [" + error.ToString() + "], ex.NativeErrorCode = " + ex.NativeErrorCode + ", ex.ErrorCode=" + ex.ErrorCode, ex);
            }

            // this._updatedGreenZipFileNames.Clear(); // 避免后面再次调用本函数
        }
Example #4
0
File: Class1.cs Project: zgren/dp2
        public static string Test()
        {
            bool bret = StringUtil0.IsInList("1", "1,3");

            return($"test{bret}");
        }
Example #5
0
        // 从 Web 服务器安装或者升级绿色版
        // parameters:
        //      style   处理风格:
        //              delayExtract    是否延迟展开 .zip 文件?
        //              updateGreenSetupExe 是否要一并更新 greensetup.exe?
        //              clearStateFile  处理前是否清除 install_state.txt 文件?(意味着不会受到文件内容为 downloading 的影响)
        // result.Value:
        //      -1  出错
        //      0   经过检查发现没有必要升级
        //      1   成功
        //      2   成功,但需要立即重新启动计算机才能让复制的文件生效
        public static async Task <NormalResult> InstallFromWeb(string downloadUrl,
                                                               string installDirectory,
                                                               string style,
                                                               //bool delayExtract,
                                                               //bool updateGreenSetupExe,
                                                               CancellationToken token,
                                                               Delegate_setProgress setProgress)
        {
            bool delayExtract        = StringUtil0.IsInList("delayExtract", style);
            bool updateGreenSetupExe = StringUtil0.IsInList("updateGreenSetupExe", style);
            bool clearStateFile      = StringUtil0.IsInList("clearStateFile", style);

            string strBaseUrl = downloadUrl;

            if (strBaseUrl[strBaseUrl.Length - 1] != '/')
            {
                strBaseUrl += "/";
            }

            string strBinDir = installDirectory;

            string strUtilDir = GetUtilDir(strBinDir);

            setProgress?.Invoke(-1, -1, -1, "开始自动更新(绿色安装)");

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

            if (check_result.Value == -1)
            {
                setProgress?.Invoke(-1, -1, -1, $"检查下载状态时出错: {check_result.ErrorInfo}");
                return(check_result);
            }

            if (clearStateFile && (check_result.Value == 1 || check_result.Value == 3))
            {
                WriteStateFile(strBinDir, null);
                // 继续处理
            }
            else if (check_result.Value == 1 ||
                     check_result.Value == 3 ||
                     check_result.Value == 5)
            {
                if (check_result.Value == 1)
                {
                    setProgress?.Invoke(-1, -1, -1, "前一次下载正在进行,尚未完成。本次下载被放弃");
                }
                if (check_result.Value == 3)
                {
                    setProgress?.Invoke(-1, -1, -1, "前一次下载已经完成,但尚未展开安装。本次下载被放弃");
                }
                if (check_result.Value == 5)
                {
                    setProgress?.Invoke(-1, -1, -1, "前一次下载和安装已经完成,等待计算机重启生效。本次下载被放弃");
                }
                return(new NormalResult());
            }


            // 希望下载的文件。纯文件名
            List <string> filenames = new List <string>()
            {
                // "greenutility.zip", // 这是工具软件,不算在 dp2circulation 范围内
                "app.zip",
                "data.zip"
            };

            if (updateGreenSetupExe)
            {
                filenames.Insert(0, "greensetup.exe");
            }

            // 发现更新了并下载的文件。纯文件名
            List <FileNameAndLength> updated_filenames = new List <FileNameAndLength>();

            // 需要确保最后被展开的文件。如果下载了而未展开,则下次下载的时候会发现文件已经是最新了,从而不会下载,也不会展开。这就有漏洞了
            // 那么就要在下载和展开这个全过程中断的时候,记住删除已经下载的文件。这样可以迫使下次一定要下载和展开
            List <string> temp_filepaths = new List <string>();

            try
            {
                // 第一步,先检查更新的文件,计算需要下载的尺寸
                long downloadLength = 0;
                // List<string> changed_filenames = new List<string>();
                foreach (string filename in filenames)
                {
                    if (token.IsCancellationRequested)
                    {
                        return new NormalResult
                               {
                                   Value     = -1,
                                   ErrorCode = "canceled"
                               }
                    }
                    ;

                    string strUrl = // "http://dp2003.com/dp2circulation/v2/"
                                    strBaseUrl
                                    + filename;
                    string strLocalFileName = Path.Combine(strBinDir, filename).ToLower();

                    // 判断 http 服务器上一个文件是否已经更新
                    // return:
                    //      -1  出错
                    //      0   没有更新
                    //      1   已经更新
                    var result = await GetServerFileInfo(strUrl,
                                                         File.GetLastWriteTimeUtc(strLocalFileName));

                    if (result.Value == -1)
                    {
                        WriteStateFile(strBinDir, "downloadError");

                        return(result);
                    }

                    if (File.Exists(strLocalFileName) == true)
                    {
                        // this.DisplayBackgroundText("检查文件版本 " + strUrl + " ...\r\n");
                        if (result.Value == 1)
                        {
                            updated_filenames.Add(new FileNameAndLength
                            {
                                FileName   = filename,
                                FileLength = result.ContentLength
                            });
                            downloadLength += result.ContentLength;
                        }
                    }
                    else
                    {
                        updated_filenames.Add(new FileNameAndLength
                        {
                            FileName   = filename,
                            FileLength = result.ContentLength
                        });
                        downloadLength += result.ContentLength;
                    }
                }

                // 设置进度条总长度
                setProgress?.Invoke(0, downloadLength, 0, null);

                int  downloadCount = 0;
                long downloaded    = 0;
                foreach (var info in updated_filenames)
                {
                    if (token.IsCancellationRequested)
                    {
                        if (downloadCount > 0)
                        {
                            WriteStateFile(strBinDir, "downloadError");
                        }
                        return(new NormalResult
                        {
                            Value = -1,
                            ErrorCode = "canceled"
                        });
                    }

                    string strUrl = // "http://dp2003.com/dp2circulation/v2/"
                                    strBaseUrl
                                    + info.FileName;
                    string strLocalFileName = Path.Combine(strBinDir, info.FileName).ToLower();

                    // 特殊一点,先下载到一个临时文件名下
                    if (info.FileName == "greensetup.exe")
                    {
                        strLocalFileName = Path.Combine(strBinDir, info.FileName + ".tmp").ToLower();
                    }

                    /*
                     * if (File.Exists(strLocalFileName) == true)
                     * {
                     *  // this.DisplayBackgroundText("检查文件版本 " + strUrl + " ...\r\n");
                     *
                     *  // 判断 http 服务器上一个文件是否已经更新
                     *  // return:
                     *  //      -1  出错
                     *  //      0   没有更新
                     *  //      1   已经更新
                     *  var result = await GetServerFileInfo(strUrl,
                     *      File.GetLastWriteTimeUtc(strLocalFileName));
                     *  if (result.Value == -1)
                     *  {
                     *      if (downloadCount > 0)
                     *          WriteStateFile(strBinDir, "downloadError");
                     *
                     *      return result;
                     *  }
                     *  if (result.Value == 1)
                     *      updated_filenames.Add(filename);
                     #if NO
                     *  else
                     *      this.DisplayBackgroundText("没有更新。\r\n");
                     #endif
                     * }
                     * else
                     *  updated_filenames.Add(filename);
                     */

                    // if (updated_filenames.IndexOf(filename) != -1)
                    {
                        WriteStateFile(strBinDir, "downloading");

                        setProgress?.Invoke(-1, -1, -1, "下载 " + strUrl + " 到 " + strLocalFileName + " ...\r\n");

                        var result = await DownloadFileAsync(strUrl,
                                                             strLocalFileName,
                                                             token,
                                                             (o, e) =>
                        {
                            // 防止越过 Maximum
                            if (downloaded + e.BytesReceived > downloadLength)
                            {
                                downloadLength = downloaded + e.BytesReceived;
                                setProgress?.Invoke(-1, downloadLength, -1, null);
                            }
                            setProgress?.Invoke(-1, -1, downloaded + e.BytesReceived, null);
                        });

                        if (result.Value == -1)
                        {
                            WriteStateFile(strBinDir, "downloadError");
                            return(result);
                        }

                        downloaded += info.FileLength;

                        // 下载成功的本地文件,随时可能被删除,如果整个流程没有完成的话
                        temp_filepaths.Add(strLocalFileName);

                        downloadCount++;
                    }
                }


#if NO
                string strGreenUtilityExe = Path.Combine(strUtilDir, "greenutility.exe");

                if (updated_filenames.IndexOf("greenutility.zip") != -1 ||
                    File.Exists(strGreenUtilityExe) == false)
                {
                    // 将 greenutility.zip 展开到 c:\dp2circulation_temp
                    string strZipFileName = Path.Combine(strBinDir, "greenutility.zip").ToLower();
                    string strTargetDir   = strUtilDir;

                    setProgress?.Invoke(0, 0, 0, "展开文件 " + strZipFileName + " 到 " + strTargetDir + " ...\r\n");
                    try
                    {
                        using (ZipFile zip = ZipFile.Read(strZipFileName))
                        {
                            foreach (ZipEntry e in zip)
                            {
                                e.Extract(strTargetDir, ExtractExistingFileAction.OverwriteSilently);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        string strError = "展开文件 '" + strZipFileName + "' 到目录 '" + strTargetDir + "' 时出现异常" + ex.Message;
                        // 删除文件,以便下次能重新下载和展开
                        try
                        {
                            File.Delete(Path.Combine(strTargetDir, "greenutility.zip"));
                        }
                        catch
                        {
                        }

                        /*
                         * ReportError("dp2circulation 展开 greenutility.zip 时出错", strError);
                         * return;
                         */
                        return(new NormalResult
                        {
                            Value = -1,
                            ErrorInfo = strError
                        });
                    }

                    updated_filenames.Remove("greenutility.zip");
                    temp_filepaths.Remove(strZipFileName);
                }
#endif

                List <string> _updatedGreenZipFileNames = new List <string>();
#if TEST
                // 测试
                this._updatedGreenZipFileNames = new List <string>();
                this._updatedGreenZipFileNames.Add("app.zip");
#else
                List <string> copy_filenames = new List <string>();

                // 给 MainForm 一个标记,当它退出的时候,会自动展开 .zip 文件完成升级安装
                _updatedGreenZipFileNames = new List <string>();
                foreach (var info in updated_filenames)
                {
                    if (info.FileName.EndsWith(".exe") == false)
                    {
                        _updatedGreenZipFileNames.Add(info.FileName);
                    }
                    else
                    {
                        copy_filenames.Add(info.FileName);
                    }
                }
#endif
                if (copy_filenames.Count > 0)
                {
                    foreach (var filename in copy_filenames)
                    {
                        string source = Path.Combine(strBinDir, filename + ".tmp");
                        string target = Path.Combine(strBinDir, filename);

                        try
                        {
                            File.Copy(source, target, true);
                            File.Delete(source);
                        }
                        catch
                        {
                            // TODO: 写入错误日志?
                        }
                    }
                }

                if (downloadCount > 0)
                {
                    WriteStateFile(strBinDir, "downloadComplete");
                }

                // 没有必要升级
                if (_updatedGreenZipFileNames.Count == 0)
                {
                    return(new NormalResult());
                }

                if (delayExtract)
                {
                    if (_updatedGreenZipFileNames.Count > 0)
                    {
                        setProgress?.Invoke(-1, -1, -1, "dp2circulation 绿色安装包升级文件已经准备就绪。当退出 dp2circulation 时会自动进行安装。\r\n");
                    }
                    else
                    {
                        setProgress?.Invoke(-1, -1, -1, "没有发现更新。\r\n");
                    }

                    temp_filepaths.Clear(); // 这样 finally 块就不会删除这些文件了
                }
                else
                {
                    temp_filepaths.Clear(); // 这样 finally 块就不会删除这些文件了

                    if (_updatedGreenZipFileNames != null && _updatedGreenZipFileNames.Count > 0)
                    {
                        setProgress?.Invoke(-1, -1, -1, "正在解压文件");

                        // TODO: 直接解压到目标位置即可
                        string files = StringUtil0.MakePathList(_updatedGreenZipFileNames);
                        // 安装软件。用 MoveFileEx 法
                        // return:
                        //      -1  出错
                        //      0   成功。不需要 reboot
                        //      1   成功。需要 reboot
                        int nRet = Install_2(strBinDir,
                                             strBinDir,
                                             files,
                                             Path.GetTempPath(),
                                             out string strError);
                        if (nRet == -1)
                        {
                            // TODO: 这里是否需要删除两个 .zip 文件以便迫使后面重新下载和展开?
                            return(new NormalResult
                            {
                                Value = -1,
                                ErrorInfo = strError
                            });
                        }
                        if (nRet == 1)
                        {
                            WriteStateFile(strBinDir, "waitingReboot");

                            return(new NormalResult
                            {
                                Value = 2   // 表示需要重启计算机
                            });
                        }

                        /*
                         * StartGreenUtility(_updatedGreenZipFileNames,
                         *  strBinDir,
                         *  waitExe);
                         */
                        WriteStateFile(strBinDir, "installed");
                    }
                }

                return(new NormalResult {
                    Value = 1
                });
            }
            catch (Exception ex)
            {
                WriteStateFile(strBinDir, "downloadError");
                return(new NormalResult
                {
                    Value = -1,
                    ErrorInfo = $"exception: {ex.Message}"
                });
            }
            finally
            {
                foreach (string filepath in temp_filepaths)
                {
                    File.Delete(filepath);
                }
            }

            /*
             * return;
             * ERROR1:
             * // ShowMessageBox(strError);
             * this.DisplayBackgroundText("绿色更新过程出错: " + strError + "\r\n");
             * ReportError("dp2circulation GreenUpdate() 出错", strError);
             */
        }