예제 #1
0
        /// <summary>
        /// アップデート処理。
        /// </summary>
        private async void OnUpdate()
        {
            isUpdateSuccess = false;

            // 本アプリの実行ファイルのディレクトリパス
            var rootDirPath = FileUtil.GetExecuteDirPath();

            // 一時ディレクトリパスを生成
            var downloadDirPath = FileUtil.CreateTempDirectory(rootDirPath);
            // ファイルパスリスト
            var downloadFilePathList = new List <string>();

            // 一時バージョンファイルパス
            var tempVersionFilePath = FileUtil.GetTempFilePath(rootDirPath);

            // アップデートスクリプトファイルパス
            var updateScriptFilePath = string.Empty;
            // アプリケーションファイルパス
            var applicationFilePath = Path.Combine(rootDirPath, appConfig.ApplicationFilePath);
            // アプリケーションディレクトリパス
            var applicationDirPath = Path.GetDirectoryName(applicationFilePath);
            // アプリケーションバージョンファイルパス
            var applicationVersionFilePath = Path.Combine(rootDirPath, appConfig.ApplicationVersionFilePath);

            try
            {
                /*
                 * ファイルのダウンロード
                 */

                // github上の最新リリース情報を取得
                using (var gitHubReleasesLatest = new GitHubReleasesLatest(this.appConfig))
                {
                    int assetsIndex = 0;

                    foreach (var assetItem in releaseLatestInfo.Assets)
                    {
                        var name               = assetItem.Name;
                        var contentType        = assetItem.ContentType;
                        var size               = assetItem.Size;
                        var browserDownloadUrl = assetItem.BrowserDownloadUrl;

                        progressForm.SetMessage(string.Format("ダウンロード数:{0} / {1} ... {2}", (assetsIndex + 1), releaseLatestInfo.Assets.Count, name));
                        progressForm.ChangeBlocks(size);

                        HttpResponseMessage releaseLatestResponse = await gitHubReleasesLatest.DownloadReleaseLatestFile(browserDownloadUrl); // 非同期なので取得まで待機する

                        if (isUpdateCancel)
                        {
                            // キャンセル
                            return;
                        }

                        if (releaseLatestResponse.StatusCode == System.Net.HttpStatusCode.OK)
                        {
                            // 正常
                            var responseContent = await releaseLatestResponse.Content.ReadAsStreamAsync(); // 非同期なので取得まで待機する

                            if (isUpdateCancel)
                            {
                                // キャンセル
                                return;
                            }

                            // 一時ファイルに書き込む
                            var downloadFilePath = Path.Combine(downloadDirPath, name);
                            using (var writer = new BinaryWriter(new FileStream(downloadFilePath, FileMode.Create)))
                            {
                                // レスポンスからデータを読み込む
                                int    readByte = 0;
                                byte[] b        = new byte[1024];
                                while ((readByte = await responseContent.ReadAsync(b, 0, b.Length)) != 0) // 非同期なので取得まで待機する
                                {
                                    if (isUpdateCancel)
                                    {
                                        // キャンセル
                                        return;
                                    }

                                    writer.Write(b, 0, readByte);

                                    progressForm.IncValue(readByte);
                                }
                            }

                            downloadFilePathList.Add(downloadFilePath);
                        }
                        else
                        {
                            // エラー発生
                            throw new Exception(string.Format("ファイルダウンロード時のエラー … HTTPステータスコード:{0}", releaseLatestResponse.StatusCode));
                        }

                        assetsIndex++;
                    }
                }

                if (isUpdateCancel)
                {
                    // キャンセル
                    return;
                }

                /*
                 * ZIPファイルの解凍
                 */
                foreach (var item in downloadFilePathList)
                {
                    if (Path.GetExtension(item) == ".zip")
                    {
                        progressForm.SetMessage(string.Format("ZIPファイル解凍中 ... {0}", Path.GetFileName(item)));
                        progressForm.ChangeMarquee();

                        ZipFile.ExtractToDirectory(item, Path.Combine(Path.GetDirectoryName(item), Path.GetFileNameWithoutExtension(item)));
                    }
                }

                if (isUpdateCancel)
                {
                    // キャンセル
                    return;
                }

                /*
                 * セキュリティブロックの解除
                 */
                progressForm.SetMessage("セキュリティロックの解除中");
                progressForm.ChangeMarquee();

                var securityUnblockExitCode = ProcessExecuteUtil.Execute(
                    "powershell"                                                                                                    // 実行ファイル
                    , string.Format("-Command \"Get-ChildItem '{0}\\*.*' -Recurse | Unblock-File\"", downloadDirPath.TrimEnd('\\')) // 実行ファイルの引数
                    , out string securityUnblockOutput                                                                              // 標準出力
                    , out string securityUnblockError                                                                               // 標準エラー出力
                    , false                                                                                                         // ユーザープロファイルのロード
                    );

                if (securityUnblockExitCode != 0)
                {
                    // エラー発生
                    throw new Exception(string.Format("セキュリティブロック解除時のエラー … エラーコード:{0}", securityUnblockExitCode));
                }

                if (isUpdateCancel)
                {
                    // キャンセル
                    return;
                }

                /*
                 * ダウンロードしたファイルからアプリケーションファイルを取得する
                 */
                var downloadApplicationFilePathList = FileUtil.FindFiles(downloadDirPath
                                                                         , (filePath) =>
                {
                    if (Path.GetFileName(filePath) == Path.GetFileName(appConfig.ApplicationFilePath))
                    {
                        return(true);
                    }

                    return(false);
                }
                                                                         , true);

                /*
                 * アップデートスクリプトの検索
                 */
                if (downloadApplicationFilePathList.Count <= 0)
                {
                    // エラー
                    throw new Exception(string.Format("アプリケーションファイルの検索エラー … アプリケーションファイルパス:{0}", appConfig.ApplicationFilePath));
                }

                var downloadApplicationDirPath = string.Empty;
                foreach (var downloadApplicationFilePath in downloadApplicationFilePathList)
                {
                    downloadApplicationDirPath = Path.GetDirectoryName(downloadApplicationFilePath);
                    var tempFilePath = Path.Combine(downloadApplicationDirPath, appConfig.UpdateScriptFilePath);
                    if (File.Exists(tempFilePath))
                    {
                        // OK
                        updateScriptFilePath = tempFilePath;
                        break;
                    }
                }

                if (string.IsNullOrEmpty(updateScriptFilePath))
                {
                    // エラー
                    throw new Exception(string.Format("アップデートスクリプトの検索エラー … アップデートスクリプトファイルパス:{0}", appConfig.UpdateScriptFilePath));
                }

                /*
                 * アップデートスクリプトの実行
                 */
                progressForm.SetMessage("アップデートの実行中");
                progressForm.ChangeMarquee();

                var updateScriptArgs = string.Format("\"{0}\" \"{1}\" \"{2}\""
                                                     , applicationDirPath.TrimEnd('\\')
                                                     , downloadDirPath.TrimEnd('\\')
                                                     , downloadApplicationDirPath.TrimEnd('\\'));

                logger.Info(string.Format("アップデートスクリプトの実行 ... {0} {1}"
                                          , updateScriptFilePath
                                          , updateScriptArgs
                                          ));

                var updateScriptExitCode = ProcessExecuteUtil.Execute(
                    updateScriptFilePath            // 実行ファイル
                    , updateScriptArgs              // 実行ファイルの引数
                    , out string updateScriptOutput // 標準出力
                    , out string updateScriptError  // 標準エラー出力
                    , false                         // ユーザープロファイルのロード
                    );

                if (updateScriptExitCode != 0)
                {
                    // エラー発生
                    throw new Exception(string.Format("アップデートスクリプト実行時のエラー … エラーコード:{0}", updateScriptExitCode));
                }

                /*
                 * バージョンファイルの更新
                 */
                progressForm.SetMessage("バージョンファイルの更新");
                progressForm.ChangeMarquee();

                FileUtil.WriteFileContents(tempVersionFilePath, releaseLatestInfo.TagName);

                if (File.Exists(applicationVersionFilePath))
                {
                    File.Delete(applicationVersionFilePath);
                }
                File.Move(tempVersionFilePath, applicationVersionFilePath);

                isUpdateSuccess = true;
            }
            catch (Exception ex)
            {
                if (ex is AggregateException)
                {
                    foreach (var e in ((AggregateException)ex).InnerExceptions)
                    {
                        logger.Error(e, "Update error");
                    }
                }
                else
                {
                    logger.Error(ex, "Update error");
                }

                MessageBox.Show(this
                                , "アップデート中にエラーが発生しました。\n\n" +
                                "詳細はログファイルを確認してください。\n" +
                                "ファイルパス:" + logger.FilePath
                                , "アップデートエラー"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                // 後処理
                if (Directory.Exists(downloadDirPath))
                {
                    Directory.Delete(downloadDirPath, true);
                }

                if (File.Exists(tempVersionFilePath))
                {
                    File.Delete(tempVersionFilePath);
                }

                // 進行状況フォームを閉じる
                progressForm.Close();
            }
        }
예제 #2
0
        /// <summary>
        /// バージョンをチェックする。
        /// </summary>
        private async void OnCheckVersion()
        {
            isVersionCheckSuccess = false;

            try
            {
                /*
                 * ローカルアプリのバージョン情報を取得
                 */
                var appVersoinGetter = new AppVersionGetter(appConfig);
                var appVersionLocal  = appVersoinGetter.GetFromLocalApp();

                /*
                 * github上の最新リリース情報を取得
                 */
                using (var gitHubReleasesLatest = new GitHubReleasesLatest(this.appConfig))
                {
                    var releaseLatestResponse = await gitHubReleasesLatest.FetchReleaseLatestInfo(); // 非同期なので取得まで待機する

                    if (releaseLatestResponse.StatusCode == System.Net.HttpStatusCode.OK)
                    {
                        // 正常
                        var responseContent = await releaseLatestResponse.Content.ReadAsStringAsync(); // 非同期なので取得まで待機する

                        releaseLatestInfo = JsonUtil.Deserialize <GitHubReleaseLatestInfo>(responseContent);
                    }
                    else
                    {
                        // エラー発生
                        throw new Exception(string.Format("最新リリース情報取得時のエラー … HTTPステータスコード:{0}", releaseLatestResponse.StatusCode));
                    }
                }

                // 最新アプリのバージョン情報を取得
                var appVersionLatest = new VersionInfo(releaseLatestInfo.TagName);

                // アプリケーションバージョンチェックを実施する
                var appVersionChecker = new AppVersionChecker(appConfig);
                var needUpdate        = appVersionChecker.NeedUpdate(
                    appVersionLocal,
                    appVersionLatest);

                if (needUpdate)
                {
                    // 更新が必要な場合
                    btnUpdate.Enabled = true;
                }
                else
                {
                    // 更新不要
                    btnUpdate.Enabled = false;
                }

                // UIに反映
                txtLocalVersion.Text  = appVersionLocal.GetVersion();
                txtLatestVersion.Text = appVersionLatest.GetVersion();

                isVersionCheckSuccess = true;
            }
            catch (Exception ex)
            {
                if (ex is AggregateException)
                {
                    foreach (var e in ((AggregateException)ex).InnerExceptions)
                    {
                        logger.Error(e, "Version check error");
                    }
                }
                else
                {
                    logger.Error(ex, "Version check error");
                }

                MessageBox.Show(this
                                , "バージョンチェック中にエラーが発生しました。\n" +
                                "ネットワーク通信に失敗したか、設定ファイルなどに不備があります。\n\n" +
                                "詳細はログファイルを確認してください。\n" +
                                "ファイルパス:" + logger.FilePath
                                , "バージョンチェックエラー"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                // 進行状況フォームを閉じる
                progressForm.Close();
            }
        }