diff --git a/.gitignore b/.gitignore index 219172306..6307a98d4 100644 --- a/.gitignore +++ b/.gitignore @@ -285,4 +285,19 @@ __pycache__/ *.btp.cs *.btm.cs *.odx.cs -*.xsd.cs \ No newline at end of file +*.xsd.cs + +# -------------------------------------------------- +# Open棟梁 build outputs +# ビルド bat / csproj の OutputPath が出力するディレクトリ。 +# ※ 既存の "!**/packages/build/" と衝突しないよう、 +# あえて汎用の "Build/" ではなくパスを固定している +# (core.ignoreCase=true の環境では Build/ が build/ にも一致するため)。 +# -------------------------------------------------- +/root/programs/*/Frameworks/Infrastructure/Build/ +/root/programs/*/Frameworks/Infrastructure/Build_net48/ +/root/programs/*/Frameworks/Infrastructure/Build_netcore100/ +/root/programs/*/Frameworks/Infrastructure/*/RichClient/Build_net48/ +/root/programs/*/Frameworks/Infrastructure/ServiceInterface/*/dll/ +/root/programs/*/Samples/WS_sample/Build/ +/root/programs/*/Samples4NetCore/Legacy/WS_sample/Build/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..47ab51e18 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,141 @@ +# プロジェクト ポリシー +アプリケーション・フレームワーク + +https://github.com/OpenTouryoProject/OpenTouryo/ + +と、ソレを使用したサンプル・アプリケーションの開発エージェント用。 + +環境のセットアップとビルド手順は [root/Readme.ja.md](root/Readme.ja.md) を参照。 +本書は、その上で**エージェントが守るべきこと**と、**どの文書を見るか**を示す。 + +**プロジェクト共通の投稿規約は [Contributing.ja.md](Contributing.ja.md) に従う。** +コメント量の目安、クロスコンパイルと下位互換の方針、ブランチ運用(git-flow)、 +"プルリクエスト" の粒度は、人もエージェントも同じ規約による。 +本書は、そこに書かれていない**エージェント固有の制約**を扱う。 + +### Git 操作は行わない(状態を変える操作をしない) + +**成果物の検収は人が行う。** エージェントは作業結果をワーキング ツリーに残すところまでを担当し、 +Git 操作は人が手動で行う。 + +したがって、指示がない限り次を実行してはならない。 + +- `git add` / `commit` / `push`(検収前・未レビューの変更を確定・送信しない) +- `git checkout` / `switch` / `branch` / `reset` / `restore` / `stash`(人の作業状態や未保存の作業を壊す) + +**参照系は制限しない。** 何を変更したかを正確に報告するために必要なため、次は自由に実行してよい。 + +- `git status` / `diff`(`--cached` 含む)/ `log` / `show` / `ls-files` / `check-ignore` / `blame` + +作業が完了したら**何を変更したかを報告するに留める**。コミットの要否とタイミングは人が判断する。 + + + +### GitHub 操作は gh で行う + +Issue の調査・起票・コメントは、**`gh` コマンドで実行してよい**(ブラウザ操作を人に依頼しない)。 +上記の「Git 操作は行わない」はワーキング ツリーとコミット履歴に対する制約であり、 +GitHub 側のやり取りは対象外。 + +``` +gh issue view <番号> --repo OpenTouryoProject/OpenTouryo +gh issue list --repo OpenTouryoProject/OpenTouryo +gh issue comment <番号> --repo OpenTouryoProject/OpenTouryo --body-file +gh issue create --repo OpenTouryoProject/OpenTouryo --title --body-file <path> +``` + +ただし**公開リポジトリへの投稿は取り消しにくい**ため、次を守ること。 + +- **投稿前に文面を提示し、承認を得てから実行する。** 承認なしに投稿しない +- 本文は一時ファイルに書き、`--body-file` で渡す(改行・記号の欠落を避ける) +- 投稿後は URL を報告する + +**このリポジトリでは `OsscJpDevInfra` アカウントを使用する。** +`gh auth status` に複数のアカウントが登録されていることがあるため、 +投稿前にアクティブなアカウントを確認すること。異なる場合は `gh auth switch` で切り替える。 + +``` +gh auth status # アクティブなアカウントの確認 +gh auth switch --user OsscJpDevInfra # 異なる場合は切り替え +``` + +**Issue のクローズ・ラベル変更・アサイン、PR の作成やマージは人が行う。** +これらは成果物の検収と同じ扱いとし、エージェントは提案に留める。 + +### コーディング規約は、領域ごとの ANALYSIS.md に従う + +`root/programs/CS/` 配下は領域ごとに基準が異なる。 +**コードを変更する前に、作業対象を所管する `ANALYSIS.md` を読むこと。** + +| 作業対象 | 読む文書 | +|---|---| +| `root/programs/CS/Frameworks/` | [`Frameworks/ANALYSIS.md`](root/programs/CS/Frameworks/ANALYSIS.md) | +| `root/programs/CS/Samples/` | [`Samples/ANALYSIS.md`](root/programs/CS/Samples/ANALYSIS.md) | +| `root/programs/CS/Samples4NetCore/` | [`Samples4NetCore/ANALYSIS.md`](root/programs/CS/Samples4NetCore/ANALYSIS.md) | + +各 `ANALYSIS.md` が、その領域におけるアーキテクチャ・ビルド手順・条件コンパイル・ +コーディング規約・既知の落とし穴の**一次情報**である。末尾の +「エージェント向け作業チェックリスト」には着手前に目を通すこと。 + +ファイル ヘッダの書式と**更新者名**、新規ファイルにおける Copyright ブロックの扱い、 +`.bat` の文字コードなど、**エージェントが見落としやすい指定**が含まれる。 + +規約の実体はこのファイル(AGENTS.md)には書かない。領域ごとに基準が分かれるため、 +二重管理になり、どちらが正なのか分からなくなる。 + +### ビルド・テスト・リリースの検証は、専用の文書に従う + +変更を加えたあとの**検証**は、次の文書が一次情報である。 + +| 目的 | 読む文書 | +|---|---| +| リリース時の作業全体 | [`RELEASE.md`](root/programs/RELEASE.md) | +| 全ビルドの実行と判定 | [`BUILDING.md`](root/programs/BUILDING.md) | +| 単体テストの実行と判定 | [`TESTING.md`](root/programs/TESTING.md) | +| サンプルの疎通確認 | [`SMOKETEST.md`](root/programs/SMOKETEST.md) | + +検証は次の 3 本で、いずれも終了コードで合否が分かる。**この順で実行すること。** + +```powershell +cd root\programs +.\1_BuildAll.ps1 # 全ビルド +.\2_RunAllTests.ps1 # 単体テスト +.\3_SmokeTest.ps1 # サンプルの疎通 +``` + +`2_RunAllTests.ps1` はワーキング ツリーの `Result*.txt` を書き換える(従来のバッチ運用と同じ)。 +**コミットの要否は人が判断する**ため、エージェントは差分を報告するに留める。 + +**`.ps1` は Windows PowerShell 5.1 と PowerShell 7 の両方で動くこと。** +エージェントの実行環境は 7 だが、利用者は 5.1(`powershell.exe`)で実行するため、 +7 だけで確認すると 5.1 で落ちる。**変更したら 5.1 でも実行して確かめること。** + +規約の実体は +[`Frameworks/ANALYSIS.md`](root/programs/CS/Frameworks/ANALYSIS.md) の +**8.4 節「ps1 ファイルの文字コードと、PowerShell 5.1 / 7 の両対応」**にある。 + +前提となるサービスや DB の状態が足りない場合は、**勝手に変えず、対処方法とともに報告する。** + +### 付属ツールを CLI で使うときは、各ツールの README に従う + +エージェントから実行できる(非対話の)ツールには README を置く。 + +| ツール | 読む文書 | +|---|---| +| `DaoGen_Tool`(D層自動生成ツール/墨壺) | [`README.md`](root/programs/CS/Frameworks/Tools/DaoGen_Tool/README.md) | + +**引数の一覧は README に書かない。** ツールの `/HELP` が一次情報であり、 +書き写すと二重管理になる。README には README にしか書けないこと +(実行ファイルの場所、ヘルプの出し方、踏みやすい罠、前提)を置く。 + +- **引数を組み立てる前に、まず `/HELP` を実行する** +- 終了コードだけで判断せず、**生成物の存在も確認する** + (パス区切りを誤ると、成功(`0`)を返しつつ別の場所に出力される) + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..43c994c2d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e6875c306..2927c5cd1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,86 +1,92 @@ # How to contribute -Click [here](Contributing.ja.md) for Japanese version of this file. +Click [here](Contributing.ja.md) for the Japanese version of this file. ## Programming Rules and Conventions ### Comment - - The amount of comments aim about 1/3(33%) of the amount of code. - It has set a higher ratio comment in consideration of the maintenance. - Redundant comment is unnecessary. Amount of redundant comment at the present time was about 43%. + - Aim at about 1/3 (33%) of the amount of code for the amount of comments. + - A higher comment ratio is set in consideration of the maintenance. + - Redundant comments are unnecessary. The amount of (redundant) comments at the present time was about 43%. - - Change history will continue only history of the header. - Descriptions such as start and end point of the fixes are not required. + - Change history will continue only as the history of the header, even after the introduction of Git. Descriptions such as the start and end point of the fixes are not required. ### Coding - - Writing of duplicate code and information has been prohibited in this project. - This is "Once and Only Once" or "Don't repeat yourself". + - Writing duplicate code and information is prohibited in this project. + This is "Once and Only Once" or "Don't repeat yourself". - - Please keep in mind that it is limited to the statement - that can be used in run-time which was specified in the project file. + - This project is cross-compiled for C#, VB, .NET Framework (net48) and .NET Core (net10.0). + However, the VB version is provided only for .NET Framework (net48). - For example, Contained the support of VS 2010 and .NET 3.5 previously - (The current support is from VS 2015 and .NET 4.6 to latest version). - e.g. , such as async/await keyword that can not be used in VS 2010 and .NET 3.5 has not been used in this project. + - Backward compatibility is highly maintained, and breaking changes are kept to a minimum. + - When supporting both a new and an old runtime, the implementation is aligned with the old one (e.g. async/await was not used while the support of VS 2010 and .NET 3.5 was included). + - Because .NET Framework (net48) and .NET Core (net10.0) are different lines, they are cross-compiled by using conditional compilation (preprocessor). + - Breaking changes are basically for the cases of discontinuation on the runtime side, and a sufficient "obsolete" period is provided before the change. + +### Coding agent +The policy for making use of it is described in [AGENTS.md](AGENTS.md). ## C#, VB - Provision of VB version is not required. - If necessary, we will converte to VB by using the Sharpdeveloper. + Provision of the VB version is not required. If necessary, we will convert it to VB by using tools (Sharpdeveloper, generative AI). ## Flow ### GitHub Flow - GitHubFlow is not adopted because there is no culture of the shipment - that test and push constantly and deploy the product every day. + "Push the product every day, test it constantly and deploy it." + GitHub Flow is not adopted because there is no such culture of shipment in this project. - - GitHub Flow - Scott Chacon(原文) - http://scottchacon.com/2011/08/31/github-flow.html - - 上記記事の日本語訳 - https://gist.github.com/Gab-km/3705015 + - GitHub Flow - Scott Chacon (original) + https://scottchacon.com/2011/08/31/github-flow/ + - Japanese translation of the above article + https://gist.github.com/Gab-km/3705015 ### git-flow - This repository is based on the branch model of the the following URL. - - develop branch and master branch has been permanent. - - Create other branches as needed. + This repository is based on the git-flow branching model in "Reference" below. + + - The master and develop branches are permanent. + - Other branches are created as needed. #### Reference - A successful Git branching model » nvie.com - http://nvie.com/posts/a-successful-git-branching-model/ + https://nvie.com/posts/a-successful-git-branching-model/ - 見えないチカラ A successful Git branching model を翻訳しました - http://keijinsonyaban.blogspot.jp/2010/10/successful-git-branching-model.html + http://keijinsonyaban.blogspot.com/2010/10/a-successful-git-branching-model.html + + Note that a note by the author (Note of reflection, 2020/03/05) has been added to the original article above, + which states that git-flow is not recommended for web applications with continuous delivery and so on. + As described above, this project is not operated to ship every day, so git-flow is adopted. ### About the "pull request" #### Size of the "pull request" - - Reduce the size of "commit" and "pull request" for review of "pull request". + - Reduce the size of the "commit" and the "pull request" for the review of the "pull request". - - If multiple tasks of bug or enhance are present in the one "pull request", one delay affects the other. + - If multiple tasks of bugs or enhancements are present in one "pull request", one delay affects the others. - - For this reason, you must create a feature branch for each task of bug or enhance. - After that, ask the review to me by sending each time "pull request" from the feature branch. + - For this reason, you need to create a feature branch for each task of a bug or an enhancement. + After that, ask me for a review by sending a "pull request" from the feature branch each time. - - Also, please do not commit unnecessary changes that indentation is changed by the IDE or editor. + - Also, please do not commit unnecessary changes such as indentation changed by the IDE or the editor. #### Send a "pull request" - - Fork to the repository by each user from OpenTouryo repository. - After having done fork, create a feature branch from the develop branch. + - Fork from the OpenTouryo repository to the repository of each user. + After that, create a feature branch from the develop branch and work on it. + + - Send the "pull request" from your feature branch to the develop branch of the fork source. - - Send "pull request" to the "develop branch of fork source" from your feature branch. + - If the develop branch of the fork source has been changed, do "pull" or "fetch & merge" to the feature branch. - - If "develop branch of fork source" was changed, - then you should do the "pull" or "fetch & merge" operation to the feature branch. +#### Notes for the "pull request" + - Keep the develop / feature branches up to date with the following steps. -#### Notes for "pull request" - - You keep the develop / feature branch up to date as follows. + 1. "pull" or "fetch & merge" the develop branch of OpenTouryo into your develop / feature branch. + 2. Recreate the feature branch from your develop branch. + 3. Reflect the changes to the feature branch. + 4. Test and push, and then send the "pull request". - - "pull" or "fetch & merge" OpenTouryo develop branch from your develop / feature branch. - and you recreate the feature branch from your develop branch and you reflect changes to the feature branch. - After that, test and push, and finally send "pull request". + - These steps serve the following two purposes. - - There is also a way to fork again instead of pull or fetch & marge, - but comments and changes that are not merged original fork source are lost. + - Keeping up with the changes of the develop branch of the fork source. + - Preventing the commit log from being contaminated by rolling back the program after an incorrect change. - - To prevent contaminating the commit log by rolling back program after the incorrect change, follow these steps. - - You recreate the feature branch from your develop branch. -   - And you reflect changes again to the feature branch. -   - After that, test and push, and finally send "pull request". + - There is also a way to fork again instead of "pull" or "fetch & merge", but the comments and the changes that are not merged into the fork source are lost. diff --git a/Contributing.ja.md b/Contributing.ja.md index 42ec4ef00..b99070764 100644 --- a/Contributing.ja.md +++ b/Contributing.ja.md @@ -6,21 +6,28 @@ ### コメント - コメント量はコード量の1/3 (33%) 程度を目安にして下さい。 - メンテナンスを考慮して、高めのコメント比率を設定しています。 - 冗長なコメントは不要です。現時点の冗長なコメントの量は43%程度でした。 + - メンテナンスを考慮して、高めのコメント比率を設定しています。 + - 冗長なコメントは不要です。現時点の(冗長な)コメントの量は43%程度でした。 - - 変更履歴はヘッダの履歴だけ継続します。修正の開始・終了などの記載は不要です。 + - 変更履歴はGit導入後もヘッダの履歴だけ継続します。修正の開始・終了などの記載は不要です。 ### コーディング - このプロジェクトでは重複したコードや情報の書き込みが禁止されています。 これは "Once and Only Once" や "Don't repeat yourself" です。 - - プロジェクトファイルで指定されたのランタイムで使用可能なステートメントに限られますので注意下さい。 - 例えば、以前はVS 2010, .NET 3.5のサポートが含まれていました(現在はVS 2015, .NET 4.6からのサポート)。 - このためVS 2010, .NET 3.5で使用できないasync/awaitキーワードなどは本プロジェクトで使用されていません。 + - C#、VB、.NET Framework 系(net48)、.NET Core 系(net10.0)のクロスコンパイルです。 + ただし、VB版は .NET Framework 系(net48)版のみの提供になります。 + + - 下位互換は高く維持し、破壊的な変更は最小限にします。 + - 新・旧ランタイムをサポートする場合は、旧に合わせた実装を行います(例:VS2010, .NET3.5サポートが含まれていた時は async/await を使用しなかった)。 + - .NET Framework系(net48)、.NET Core系(net10.0)は別系列なので条件付きコンパイル(プリプロセッサ)を使用してクロスコンパイルします。 + - 破壊的な変更は、基本的にランタイム側のdisconのケースで、変更の前に十分に「obsolete」の期間を設けます。 + +### コーディングエージェント +活用方針は [AGENTS.md](AGENTS.md) に記載してあります。 ## C#, VB - VB版の提供は必須ではありません。必要であればこちらでSharpdeveloperを使用してVBに変換します。 + VB版の提供は必須ではありません。必要であればこちらでツール(Sharpdeveloper、生成AI)を使用してVBに変換します。 ## 手順 @@ -29,21 +36,25 @@ という出荷の文化はこのプロジェクトに無い為、GitHubFlowは採用しません。 - GitHub Flow - Scott Chacon(原文) - http://scottchacon.com/2011/08/31/github-flow.html + https://scottchacon.com/2011/08/31/github-flow/ - 上記記事の日本語訳 https://gist.github.com/Gab-km/3705015 ### git-flow - このリポジトリは、次の URL の git-flow ブランチ・モデルに基づいています。 + このリポジトリは、下記「参考」の git-flow ブランチ・モデルに基づいています。 - master と develop ブランチを常設しています。 - その他のブランチは必要に応じて作成します。 #### 参考 - A successful Git branching model » nvie.com - http://nvie.com/posts/a-successful-git-branching-model/ + https://nvie.com/posts/a-successful-git-branching-model/ - 見えないチカラ A successful Git branching model を翻訳しました - http://keijinsonyaban.blogspot.jp/2010/10/successful-git-branching-model.html + http://keijinsonyaban.blogspot.com/2010/10/a-successful-git-branching-model.html + + なお上記の原典には、著者による注記(Note of reflection、2020/03/05)が追記されており、 + 継続的デリバリを行う Web アプリなどには git-flow を勧めない旨が述べられています。 + このプロジェクトは前述のとおり毎日出荷する運用ではないため、git-flow を採用しています。 ### "プルリクエスト"について @@ -58,7 +69,7 @@ - また、IDEやEditorによりインデントが変更されるような不要な修正もコミットしないで下さい。 #### "プルリクエスト"を送る - - Opentouryoリポジトリから各ユーザのリポジトリに fork します。 + - OpenTouryoリポジトリから各ユーザのリポジトリに fork します。 その後に develop ブランチから feature ブランチを作成し作業します。 - "プルリクエスト"は feature ブランチから fork 元の develop ブランチに対して送信します。 @@ -66,15 +77,16 @@ - もし fork 元の develop ブランチが変更されているようなら、feature ブランチに pull 若しくは fetch & merge をします。 #### "プルリクエスト"についての注意事項 - - あなたは、次のように develop / feature ブランチを最新の状態に維持します。 + - develop / feature ブランチは、次の手順で最新の状態に維持します。 + + 1. OpenTouryo の develop ブランチを、あなたの develop / feature ブランチへ pull 若しくは fetch & merge します。 + 2. あなたの develop ブランチから feature ブランチを再作成します。 + 3. feature ブランチへ変更を反映します。 + 4. テストおよびプッシュし、"プルリクエスト"を送ります。 - - OpenTouryoの develop ブランチを、あなたの develop / feature ブランチから pull 若しくは fetch & merge してください。 - そして、あなたはあなたの develop ブランチから feature ブランチを再作成し、あなたはfeatureブランチへの変更を反映します。 - その後、テストおよびプッシュし、"プルリクエスト"を送ります。 + - この手順は、次の 2 つを兼ねています。 - - pull や fetch & margeの代わりに再度 fork する方法もありますが、コメントや元のfork 元にマージされていない変更は失われます。 + - fork 元の develop ブランチの変更に追随すること。 + - 間違った変更の後にプログラムをロールバックして、コミットログが汚染されるのを防ぐこと。 - - 間違った変更の後にプログラムをロールバックしてコミットログが汚染されることを防止するために、次の手順に従ってください。 - - あなたは、あなたの develop ブランチから feature ブランチを再作成します。 - - そして、あなたは feature ブランチへの変更を反映します。 - - その後、テストおよびプッシュし、"プルリクエスト"を送ります。 + - pull や fetch & merge の代わりに再度 fork する方法もありますが、コメントや、fork 元にマージされていない変更は失われます。 diff --git a/README.md b/README.md index e328daf96..aa56059e6 100644 --- a/README.md +++ b/README.md @@ -7,29 +7,32 @@ Click [here](Readme.ja.md) for Japanese version of this file. The programs in this repository are developed in the following IDE/targetFramework: - IDE (Integrated Development Environment) - Visual Studio 2022 + Visual Studio 2026 - targetFramework (Run-time environment) - .NET Framework 4.8 (net48) - - .NET 8.0 (net8.0) + - .NET 10.0 (net10.0) -The name of projects and solutions include the targetFramework. -For example, the projects and solutions for net48(.NET Framework 4.8) are named {identifier}_net48.{ext}. +The name of projects and solutions include an identifier of the targetFramework. +For example, the projects and solutions for .NET Framework 4.8 are named {identifier}_net48.{ext}, +and the ones for .NET 10.0 are named {identifier}_netcore100.{ext}. + +## Documents +The documents of *Open Touryo* are stored in the [OpenTouryoDocuments](https://github.com/OpenTouryoProject/OpenTouryoDocuments) repository. -## Summary -Please refer to the following files. - [List of documents, Japanese Version](https://github.com/OpenTouryoProject/OpenTouryoDocuments/blob/master/documents/0_Introduction/ja-JP) - [Function List, Japanese Version (Excel)](https://github.com/OpenTouryoProject/OpenTouryoDocuments/blob/master/documents/0_Introduction/ja-JP/Functional_list.xlsx) -## Details -The documents are stored in [OpenTouryoDocuments](https://github.com/OpenTouryoProject/OpenTouryoDocuments) repository. -For more details, refer to the documents in [OpenTouryoDocuments](https://github.com/OpenTouryoProject/OpenTouryoDocuments) repository. - +Some of the documents are [available as a Wiki in this repository](https://github.com/OpenTouryoProject/OpenTouryo/wiki). ## Contents -### Directory - -#### [/license/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) +### [/license/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) License files are stored in this directory. -#### [/root/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/root) +### [/root/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/root) Programs, configuration files, sql files, and more are stored in this directory. + +For the setup and build steps, refer to [/root/README.md](root/README.md). + +### [AGENTS.md](AGENTS.md) +This is the **entry point** when working on this repository with a coding agent. +It summarizes the policies to follow and the links to the documents to refer to. diff --git a/Readme.ja.md b/Readme.ja.md index 385fe2ef5..8c4c44fa9 100644 --- a/Readme.ja.md +++ b/Readme.ja.md @@ -7,29 +7,32 @@ このリポジトリのプログラムは、以下のIDE/targetFramework を前提に開発しています。 - IDE(統合開発環境) - Visual Studio 2022 + Visual Studio 2026 - targetFramework(実行環境) - .NET Framework 4.8 (net48) - - .NET 8.0 (net8.0) + - .NET 10.0 (net10.0) -プロジェクトやソリューションの名前には、targetFrameworkが含まれます。 -たとえば、net48(.NET Framework 4.8) を対象としたプロジェクト・ソリューションは、"{identifier}_net48.{ext}" と命名しています。 +プロジェクトやソリューションの名前には、targetFramework の識別子が含まれます。 +たとえば、.NET Framework 4.8 を対象としたプロジェクト・ソリューションは "{identifier}_net48.{ext}"、 +.NET 10.0 を対象としたものは "{identifier}_netcore100.{ext}" と命名しています。 + +## 資料 +Open 棟梁のドキュメントは、[OpenTouryoDocuments リポジトリ](https://github.com/OpenTouryoProject/OpenTouryoDocuments)にあります。 -## 概要 -以下のファイルを参照してください。 - [資料一覧](https://github.com/OpenTouryoProject/OpenTouryoDocuments/blob/master/documents/0_Introduction/ja-JP) - [機能一覧 (Excel)](https://github.com/OpenTouryoProject/OpenTouryoDocuments/blob/master/documents/0_Introduction/ja-JP/Functional_list.xlsx) -## 詳細 -Open 棟梁のドキュメントは、[OpenTouryoDocuments リポジトリ](https://github.com/OpenTouryoProject/OpenTouryoDocuments)にあります。 -詳細は、[OpenTouryoDocuments リポジトリ](https://github.com/OpenTouryoProject/OpenTouryoDocuments)のドキュメントを参照してください。 - +一部の資料は[当該リポジトリ上でWiki化](https://github.com/OpenTouryoProject/OpenTouryo/wiki/Home.ja)されています。 ## 内容物 -### ディレクトリ - -#### [/license/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) +### [/license/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) このディレクトリには、ライセンスファイルが格納されています。 -#### [/root/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/root) +### [/root/](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/root) このディレクトリには、プログラム、設定ファイル、SQL ファイルなどが格納されています。 + +セットアップとビルドの手順は [/root/Readme.ja.md](root/Readme.ja.md) を参照してください。 + +### [AGENTS.md](AGENTS.md) +コーディング エージェントで本リポジトリを扱う場合の**入口**です。 +守るべきポリシーと、参照すべき文書への導線をまとめています。 diff --git a/root/README.md b/root/README.md index fa33cc129..a336dd936 100644 --- a/root/README.md +++ b/root/README.md @@ -1,78 +1,53 @@ # Open Touryo ## Outline -*Open Touryo* is an application framework based on .NET Framework and .NET Core. -The programs of Open Touryo are available in the following repositories: -- OpenTouryoTemplates repository - - Summary - The programs in this repository are the *development infrastructure (project template)* of the programs using Open Touryo. - And the programs are partitioned into the folders for each version of Visual Studio. - - Intended User - The *application developers* using Open Touryo. -- OpenTouryo repository (*Current repository*) - - Summary - The programs in this repository are the *matrix* of OpenTouryoTemplates repository. - (First, the features of Open Touryo are implemented in this repository. And then, the features are introduced into OpenTouryoTemplates repository.) - - Intended User - *Open source developers*. - -Therefore, the users who use Open Touryo in a system development project need to use [OpenTouryoTemplates repository](https://github.com/OpenTouryoProject/OpenTouryoTemplates). -The following contents are the usage of Open Touryo for *open source developers*. - -Click [here](Readme.ja.md) for Japanese version of this file. - -## Running sample application tasks -You can run the sample application bundled with Open Touryo according to the following steps. - -Notation *Optional*: -Open Touryo supports the following DBMSs and data providers. But the data providers, having the notation *optional*, are not included in the programs of Open Touryo. When using the DBMSs and data providers having the notation *optional*, download the data provider manually, and modify [the data access project of Open Touryo, that is DamXXX.csproj](https://github.com/OpenTouryoProject/OpenTouryo/tree/develop/root/programs/CS/Frameworks/Infrastructure/Public/Db), to refer the data provider. +*Open Touryo* is an application framework based on .NET Framework and .NET Core. + +Click [here](Readme.ja.md) for the Japanese version of this file. + +## How to run the programs for developing Open Touryo itself +- The following are the steps to run Open Touryo itself and the sample applications bundled with it. +- For the setup to develop an application *using* Open Touryo, refer to [this repository](https://github.com/OpenTouryoProject/OpenTouryoCodingAgentAssets/). +- When developing Open Touryo itself with a coding agent, read [AGENTS.md](../AGENTS.md) first. ### Install prerequisites -Install Visual Studio 2015 beforehand. -If you develop for .NET Standard or .NET Core, install Visual Studio 2017 beforehand. -see: https://docs.microsoft.com/ja-jp/dotnet/core/windows-prerequisites - -Further, when implementing or testing the *data access class*, install the DBMS(s) to be used. -Open Touryo supports the following DBMSs: -- SQL Server -(You can use an arbitrary version of SQL Server. And you can use different editions than Express Edition.) -- Oracle Database (including Express Edition) -- IBM DB2 ... optional -- HiRDB ... optional -- MySQL -- PostgreSQL +- Install Visual Studio beforehand (or Visual Studio Code with the .NET SDK and extensions). + +- Also, prepare the DBMS to be used out of the ones supported by Open Touryo. [LocalServicesOnDocker](https://github.com/NetDevInfraWGinOSSConsortium/LocalServicesOnDocker) is useful for this. + +- The supported data providers can be checked in [Touryo.Infrastructure.Public.Db](https://github.com/OpenTouryoProject/OpenTouryo/tree/develop/root/programs/CS/Frameworks/Infrastructure/Public/Db). + +- The officially supported data providers are *SQL / OLE / ODBC / ODP / MCN / NPG*. + +- *DB2 / HiRDB / OracleClient* are currently excluded, but their templates remain, so you can support them yourself by making use of agents and so on. + +- The abbreviations and the namespaces of the ADO.NET data providers + - SQL: Microsoft.Data.SqlClient + - OLE: System.Data.Odbc + - ODBC: System.Data.OleDb + - ODP: Oracle.ManagedDataAccess.Client + - MCN: MySql.Data.MySqlClient + - NPG: Npgsql + - DB2: IBM.Data.DB2 + - HiRDB: Hitachi.HiRDB + - OracleClient: System.Data.OracleClient ### Deploy Open Touryo -Copy *root* folder to just under C drive. If not, the build may fail for the Windows maximum path length limitation. - -### Obtain and deploy data providers -The correspondence between the DBMSs and the data providers is as follows. - -- Oracle - - Oracle.DataAccess.dll ... optional - - Oracle.ManagedDataAccess.dll -- IBM DB2 - - IBM.Data.DB2.dll ... optional -- HiRDB - - x86: pddndp40.dll, pddndpcore40.dll ... optional - - x64: pddndp40x.dll, pddndpcore40x.dll ... optional -- MySQL - - MySql.Data.dll -- PostgreSQL - - Npgsql.dll - -### Set up sample database +Copy the *root* folder to just under the C drive. If you copy it elsewhere, the build may fail because of the Windows maximum path length limitation. + +### Set up the sample database + +#### Make use of [LocalServicesOnDocker](https://github.com/NetDevInfraWGinOSSConsortium/LocalServicesOnDocker) + #### SQL Server -Sample application requires *Northwind* database. -So, download the setup script installer of *Northwind* database from the following Microsoft site and install. +The sample applications require the *Northwind* database. +Download the setup script of the *Northwind* database from the following Microsoft site and install it. - - Download: NorthWind and pubs Sample Databases for SQL Server 2000 - Microsoft Download Center - http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23654 +- Download: NorthWind and pubs Sample Databases for SQL Server 2000 - Microsoft Download Center + http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=23654 -When completing the installation, *SQL Server 2000 Sample Databases* folder is created in C drive. -When using SQL Server 2012 or later, open *instnwnd.sql* file in an editor and comment out the following code. -**Note**: -Because *sp_option* system stored procedure does not exist in SQL Server 2012 or later, this step is required. +When the installation succeeds, the *SQL Server 2000 Sample Databases* folder is created just under the C drive. +When using SQL Server 2012 or later, open the *instnwnd.sql* file in that folder with an editor and comment out the following code. (Because the *sp_dboption* system stored procedure does not exist in SQL Server 2012 or later) ```sql exec sp_dboption 'Northwind','trunc. log on chkpt.','true' @@ -80,449 +55,104 @@ exec sp_dboption 'Northwind','select into/bulkcopy','true' ``` Execute the following command at a command prompt. -**Note**: -In the following command, the path of the folder that contains *SQLCMD.EXE* changes according to the version of SQL Server. Execute command after confirming the path of folder in your environment. +(In the following command, the folder path of *SQLCMD.EXE* differs depending on the version of SQL Server. Confirm the folder path in your environment before executing the command) ```bat "C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE" -S localhost\SQLExpress -E -i "C:\SQL Server 2000 Sample Databases\instnwnd.sql" ``` -#### DBMSs except for SQL Server -- Create an empty database in each DBMSs. -- Create test table in the database by running C:\root\files\resource\Sql\\[DBMS Name]\TestTable.txt. - -### Build program -When using Open Touryo, it is necessary to build programs **by running the batch files using MSBuild only at the first time**. -**Note**: -Open Touryo Template Base contains two parts: -- Framework (Base class 1 and base class 2) -- Sample application (Subclass) - -It is necessary to copy the *deliverables generated by building*, that is, *dll files* to the default folder of Open Touryo. -Therefore, it is necessary to run the batch files which execute a series of build processes. - -The batch files are stored in the following folder: -- C:\root\programs\CS -- C:\root\programs\VB - -By executing `0_ExecAllBat.bat`, you can execute necessary batch files together. Refer to the table below, check the necessary batch to be executed, customize `0_ExecAllBat.bat` as necessary, and execute it. - -<table Border="1"> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">#</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">Batch file name </td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">Description</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="2" rowspan="1">Existence</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">C#</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">VB</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">1</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">0_ExecAllBat.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Perform a batch build using the following files: Customize as needed.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">2</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">1_DeleteDir.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Delete (Clean up) the folders that are generated by building.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">3</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">1_DeleteFile.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Delete (Clean up) the temporary files. </td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">4</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net45.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Framework 4.5.2. </td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">5</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net46.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Framework 4.6. </td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">6</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net47.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Framework 4.7. </td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">7</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net48.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Framework 4.8.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">8</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_netstd20.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Standard 2.0. </td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">9</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_netstd21.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Standard 2.1.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore30.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET Core 3.0.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore50.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET 5.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore60.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the framework (Base class 1 and library part) to make NuGet package that targets .NET 6.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">11</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net45.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Framework 4.5.2.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">12</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net46.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Framework 4.6.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">13</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net47.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Framework 4.7.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">14</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net48.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Framework 4.8.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">15</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net45.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET Framework 4.5.2.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">16</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net46.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET Framework 4.6.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">17</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net47.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET Framework 4.7.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">18</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net48.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET Framework 4.8.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">19</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore20.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Core 2.0.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore30.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET Core 3.0.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore50.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET 5.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore60.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework (base class 2, library part) of Business namespace that targets .NET 6.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore30.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET Core 3.0.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore50.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET 5.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore60.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build a framework for rich client application (base class 2, library part) of Business namespace that targets .NET 6.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">22</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_CopyAssemblies.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Copy the primary output of the above build to the reference folder.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">23</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_Framework_Tool.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based tools bundled with Open Touryo.</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">24</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_Framework_ToolCore.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based tools bundled with Open Touryo.</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">25</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_Bat_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based sample application. (Batch application)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">26</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_BatCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based sample application. (Batch application)</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">27</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_2CS_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based sample application. (Two-tier client server application)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">28</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_2CSCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based sample application. (Two-tier client server application)</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">29</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">6_Build_WSSrv_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based sample application. (Web services (Server-side logic))</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">30</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">6_Build_WSSrvCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based sample application. (Web services (Server-side logic))</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">31</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">7_Build_Framework_WS.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based framework. (Service interface)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">32</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">7_Build_Framework_WSCore.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based framework. (Service interface)</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">33</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">8_Build_WSClnt_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Framework-based sample application. (Web service client) </td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">34</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">8_Build_WSClntCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the .NET Core-based sample application. (Web service client) </td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">35</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">10_Build_WebApp_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the sample web application. (ASP.NET)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">36</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">10_Build_WebAppCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build the sample web application. (ASP.NET Core)</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">37</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">99_BuildLibsAtOtherRepos.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file for to use the Business namespace of the repository in other repositories. (using OpenTouryoTemplates-master branch)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">38</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">99_BuildLibsAtOtherReposInTimeOfDev.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file for to use the Business namespace of the repository in other repositories. (using OpenTouryo-develop branch)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">39</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Perform batch build and execution of the following test code.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">40</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_Public.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build and execute the test code of the following Public namespace.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">41</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecCUI.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build and execute the CUI test code of the following Public.Security namespace.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">42</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecCUI.sh</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build and execute the CUI test code of the following Public.Security namespace usin WSL.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">43</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecGUI.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Build and execute the GUI test code of the following Public.Security namespace.</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">44</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net45.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file to switch packages.config when creating NuGet package. (for .NET Framework 4.5.2)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">45</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net46.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file to switch packages.config when creating NuGet package. (for .NET Framework 4.6)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">46</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net47.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file to switch packages.config when creating NuGet package. (for .NET Framework 4.7)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">47</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net48.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Batch file to switch packages.config when creating NuGet package. (for .NET Framework 4.8)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">48</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_Common.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Common settings (for MSBuild)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">49</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_Common2.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Common settings (for Visual Studio)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -</table> - -<div style="font-size: small"> - <span style="color: red;">*1</span> Need to run when making NuGet package.<br /> - <span style="color: red;">*2</span> Need to run when developing rich client application.<br /> - <span style="color: red;">*3</span> Need to run when developing application that targets .NET Standard or .NET Core.<br /> - <span style="color: red;">*4</span> Select according to the actual architecture. -</div> - -- If necessary, revise the environment variable *BUILDFILEPATH* in z_Common.bat according to the build environment. - -- The libraries which are used by Open Touryo Template Base for Visual Studio 2015 are downloaded by NuGet. NuGet libraries might not be downloaded normally under proxy environment. So, when using proxy environment, create environment variable *http_proxy* as follows: - - Open *C:\root\programs\CS\z_Common.bat* and *C:\root\programs\VB\z_Common.bat* in an editor. - - By default, the code which creates environment variable *http_proxy* is commented. - So, uncomment this code by removing '@rem'. - - Set your proxy information in environment variable *http_proxy*. - -- When the following error occurred at build time, install *Windows SDK for Windows 8*. (Refer to [issue of Open Touryo](https://github.com/OpenTouryoProject/OpenTouryoTemplates/issues/48#issuecomment-241349223).) -``` -C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2863,5): error MSB3086: Task could not find "AL.exe" using the SdkToolsPath "" or the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools-x86". Make sure the SdkToolsPath is set and the tool exists in the correct processor specific location under the SdkToolsPath and that the Microsoft Windows SDK is installed +#### DBMSs other than SQL Server +- Create an empty database in each DBMS. +- Create the tables for testing by running C:\root\files\resource\Sql\\[DBMS name]\TestTable.txt. + +### Build the programs +- To build the programs of Open Touryo, run the build batch files. + +- The build batch files are stored in the following folders. + - C:\root\programs\ + - C:\root\programs\CS + - C:\root\programs\VB + +#### Structure of the build batch files + +**The number at the beginning of a file name indicates the build order.** +The build proceeds from the smaller numbers, stacking up in the order of +infrastructure, tools, and then sample applications. + +| Number | Role | +|---|---| +| `0_` | Batch execution (`0_ExecAllBat.bat` calls the following in order) | +| `1_` | Clean up (deleting `bin` / `obj` / `packages` and so on) | +| `2_` | Framework itself (the assemblies to be packed into NuGet packages) | +| `3_` | Business layer (the base classes and templates for business code) | +| `4_` | Copying assemblies for reference, and the bundled tools | +| `5_` `6_` `8_` `10_` | Sample applications | +| `7_` | Service interface for web services (on the framework side) | +| `9_` | (Not used on the C# side. Used for the WPF client on the VB side) | +| `y_` | Test code | +| `z_` | Common processing (called from the beginning of each batch file. Not run by itself) | + +- **By executing `0_ExecAllBat.bat`, everything from the infrastructure to the + sample applications is built.** The individual batch files are for rebuilding only a part. +- **`y_` (the test code) is not included in `0_ExecAllBat.bat`.** To run the unit tests, + use `2_RunAllTests.ps1` described below, or run the `y_` batch files individually. +- The file names containing `Core`, or `netcore100`, target .NET 10.0. + The others (`net48`) target .NET Framework 4.8. +- **The clean up of `1_` is executed repeatedly**, because the infrastructure and the + sample applications are rebuilt at different timings. Therefore, when the whole build + has finished, no intermediate files remain except for the ones built last. + +#### Common processing (z_Common.bat) + +- Each batch file calls `z_Common.bat` at its beginning, which provides the following: + - **Resolving the build tool** ... MSBuild is located by `vswhere` (independent of the edition) + - **Build configuration** ... `BUILD_CONFIG` (Debug / Release) and `DEBUG_TYPE` + - **NuGet settings** ... the proxy, and the MSBuild to be used on restore + +- `z_Common2.bat` is the **devenv version** of the same. It remains for the cases where + a build does not pass with MSBuild but passes with devenv. Normally it is not used. + +- The libraries used by Open Touryo are downloaded via NuGet. Therefore, the NuGet libraries might not be downloaded normally under a proxy environment. When using a proxy environment, define the *http_proxy* environment variable as follows. + - Open C:\root\programs\CS\z_Common.bat and C:\root\programs\VB\z_Common.bat with a text editor. + - By default, the part that defines the *http_proxy* environment variable is commented out, so remove "@rem" to uncomment it. + - Set your proxy information in the *http_proxy* environment variable. + +#### Verification after the build + +Confirming that the build passes, running the unit tests, and checking that the sample +applications work can be done with the scripts in `C:\root\programs\`. +**All of them report the result by their exit code.** + +```powershell +cd C:\root\programs +.\0_RunAll.ps1 # Runs the following three together ``` - -### Start ASP.NET state service -Open a command prompt as an administrator and execute the following commands. + +| Script | Description | +|---|---| +| `1_BuildAll.ps1` | Builds everything (equivalent to `0_ExecAllBat.bat`), aggregating errors and warnings | +| `2_RunAllTests.ps1` | Runs the unit tests and compares the results with the previous ones | +| `3_SmokeTest.ps1` | Starts the sample applications and checks that they work | + +For the procedures and the criteria, refer to +[`BUILDING.md`](programs/BUILDING.md) / [`TESTING.md`](programs/TESTING.md) / +[`SMOKETEST.md`](programs/SMOKETEST.md) in the same folder. +The whole release procedure is summarized in [`RELEASE.md`](programs/RELEASE.md). + +### Start the ASP.NET state service +Open a command prompt as an administrator and execute the following commands. ```bat sc config aspnet_state start= auto net start aspnet_state ``` -### Run the sample application -Open the following file. -- Open web.config or app.config (for .NET Core, appsettings.json) and revise the values in *connectionStrings* section according to the actual database environment. +### Run the sample applications +- Open the following files. +- Open web.config or app.config (appsettings.json in the case of .NET Core), and +modify the values of the connectionString section according to your actual database environment. - Run the sample application. -At the login screen, enter the arbitrary alphanumeric characters. (By default, the password authentication is not executed.) +If a login screen appears, enter arbitrary alphanumeric characters. (Password authentication is not performed by default) -#### Web application: +#### Web applications: - ASP.NET Web Forms - C:\root\programs\CS\Samples\WebApp_sample\WebForms_Sample\WebForms_Sample.sln - C:\root\programs\VB\Samples\WebApp_sample\WebForms_Sample\WebForms_Sample.sln @@ -530,7 +160,7 @@ At the login screen, enter the arbitrary alphanumeric characters. (By default, t - C:\root\programs\CS\Samples\WebApp_sample\MVC_Sample\MVC_Sample.sln - C:\root\programs\VB\Samples\WebApp_sample\MVC_Sample\MVC_Sample.sln -#### Two-tier client server application: +#### Two-tier client server applications: - Windows Forms - C:\root\programs\CS\Samples\2CS_sample\2CSClientWin_sample\2CSClientWin_sample.sln - C:\root\programs\VB\Samples\2CS_sample\2CSClientWin_sample\2CSClientWin_sample.sln @@ -538,9 +168,9 @@ At the login screen, enter the arbitrary alphanumeric characters. (By default, t - C:\root\programs\CS\Samples\2CS_sample\2CSClientWPF_sample\2CSClientWPF_sample.sln - C:\root\programs\VB\Samples\2CS_sample\2CSClientWPF_sample\2CSClientWPF_sample.sln -#### Three-tier client server application: +#### Three-tier client server applications: - Windows Forms - - Windows forms application + - Ordinary Windows Forms application - C:\root\programs\CS\Samples\WS_sample\WSClient_sample\WSClientWin_sample\WSClientWin_sample.sln - C:\root\programs\VB\Samples\WS_sample\WSClient_sample\WSClientWin_sample\WSClientWin_sample.sln - ClickOnce application @@ -549,48 +179,39 @@ C:\root\programs\CS\Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSC - C:\root\programs\CS\Samples\WS_sample\WSClient_sample\WSClientWPF_sample\WSClientWPF_sample.sln - C:\root\programs\VB\Samples\WS_sample\WSClient_sample\WSClientWPF_sample\WSClientWPF_sample.sln -### .NET Core application +### .NET Core applications + +**There is currently no plan to provide a .NET Core version for VB.** All of the following are for C# only. #### Infrastructure: -- C# - - C:\root\programs\CS\Frameworks\Infrastructure - - C:\root\programs\CS\Frameworks\Infrastructure\ServiceInterface\ASPNETWebServiceCore -- VB -... +- C:\root\programs\CS\Frameworks\Infrastructure +- C:\root\programs\CS\Frameworks\Infrastructure\ServiceInterface\ASPNETWebServiceCore #### Tools: -- C# - - C:\root\programs\CS\Frameworks\Tools -- VB -... +- C:\root\programs\CS\Frameworks\Tools + +#### Sample applications: +- C:\root\programs\CS\Samples4NetCore -#### Sample application: -- C# - - C:\root\programs\CS\Samples4NetCore -- VB -... ## Other items of note ### Copyright and license -Refer to [License](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) directory. +Refer to the [License](https://github.com/OpenTouryoProject/OpenTouryo/tree/master/license) directory. ### Bug fix -If you find the bug while you are using Open Touryo, create an new [issue](https://github.com/OpenTouryoProject/OpenTouryo/issues). -Open Touryo community confirms the issue and takes appropriate actions. - -### How to create NuGet packages -For the method of creating Open Touryo NuGet packages, see [this article](https://github.com/OpenTouryoProject/OpenTouryo/wiki/HowToCreateOpenTouryoNuGetPackages). +If you find a bug while using Open Touryo, report it as an [issue](https://github.com/OpenTouryoProject/OpenTouryo/issues). +The community will check the content and deal with it appropriately. -### Obtaining libraries, exporting control prodedures, attaching to license -- The libraries that can be obtained from package manager, that is NuGet or npm, are not bundled in Open Touryo. So, you don't have to export the libraries. -- If necessary, you have to obtain and export the other libraries, that is the libraries that can not be obtained from package manager, on your own. In this case, you have to attach the license of the libraries to be used to the license of Open Touryo. +### Obtaining libraries, export control procedures, and attaching to the license +- The libraries that can be obtained from a package manager such as NuGet or npm are not bundled with Open Touryo, so they do not need export control. +- The other libraries, that is, the ones that cannot be obtained from a package manager, need to be obtained, bundled, and exported by yourself as necessary. In that case, the licenses of the libraries you use need to be attached to the license of Open Touryo. ### Reference -The documents in *OpenTouryoDocument repository* are useful when using Open Touryo. +The documents in the OpenTouryoDocuments repository are available for using Open Touryo. - [Introduction](https://github.com/OpenTouryoProject/OpenTouryoDocuments/tree/master/documents/0_Introduction) -You can see the introduction materials, such as PowerPoint slides. +The overview documents of Open Touryo (PowerPoint slides and so on). - [User Guide](https://github.com/OpenTouryoProject/OpenTouryoDocuments/tree/master/documents/1_User_Guide) -You can confirm the structure of Open Touryo and the specification of each feature. +The mechanism of Open Touryo and the specifications of each feature. - [Tutorial](https://github.com/OpenTouryoProject/OpenTouryoDocuments/tree/master/documents/2_Tutorial) -You can see the *first step guide* of Open Touryo. +The first step guide of Open Touryo. diff --git a/root/Readme.ja.md b/root/Readme.ja.md index ac55b6e03..4170bf382 100644 --- a/root/Readme.ja.md +++ b/root/Readme.ja.md @@ -1,66 +1,44 @@ # Open 棟梁 ## 概要 -Open 棟梁は、.NET Framework と .NET Core をベースとしたアプリケーション フレームワークです。 -Open 棟梁のプログラムは、以下のリポジトリで公開しています。 -- OpenTouryoTemplates リポジトリ - - 概要 - Open 棟梁を使用したアプリケーションの**開発基盤 (テンプレート)** となるもので、 - Visual Studio のバージョンごとにフォルダが分かれている - - 想定利用者 - Open 棟梁を使用してアプリケーションを開発する人 -- OpenTouryo リポジトリ (**現在のリポジトリ**) - - 概要 - OpenTouryoTemplates リポジトリの**母体**となるもの - (Open 棟梁の各機能は、まず OpenTouryo リポジトリで開発され、 - その後 OpenTouryoTemplates リポジトリに取り込まれる) - - 想定利用者 - OSS 開発者 - -このため、システム開発プロジェクトで Open 棟梁を使用される方は、[OpenTouryoTemplates リポジトリ](https://github.com/OpenTouryoProject/OpenTouryoTemplates)を使用してください。以下、**OSS 開発者向け**に、Open 棟梁の利用方法をご紹介します。 +Open 棟梁は、.NET Framework と .NET Core をベースとしたアプリケーション フレームワークです。 このファイルの英語版は[こちら](README.md)から。 -## サンプルの実行手順 -Open 棟梁に同梱されるサンプルアプリケーションの実行手順は以下のとおりです。 - -**Optional 表記:** -以下、optional 表記のある DBMS とデータプロバイダは、Open 棟梁でサポートされていますが、Open 棟梁のプログラムには含まれていません。そのため、optional 表記のある DBMS とデータプロバイダを使う場合、必要に応じてデータプロバイダを手動でダウンロードし、[Open 棟梁のデータアクセス用のプロジェクト (DamXXX.csproj)](https://github.com/OpenTouryoProject/OpenTouryo/tree/develop/root/programs/CS/Frameworks/Infrastructure/Public/Db) から、当該データプロバイダに参照設定を張り直してください。 +## 本体開発用プログラムの実行手順 +- Open 棟梁の本体と同梱されるサンプルアプリの実行手順は以下のとおりです。 +- Open 棟梁を使用したアプリ開発を行う場合のセットアップは[コチラ](https://github.com/OpenTouryoProject/OpenTouryoCodingAgentAssets/)をご参照下さい。 +- コーディング エージェントで本体開発を行う場合は、先に [AGENTS.md](../AGENTS.md) をお読みください。 ### 前提ツールのインストール -あらかじめ、Visual Studio 2015 をインストールしておいてください。 -.NET Standard、.NET Core開発を行う場合は、Visual Studio 2017 をインストールしておいてください。 -参考: https://docs.microsoft.com/ja-jp/dotnet/core/windows-prerequisites - -また、Open 棟梁がサポートしている以下の DBMS へのデータアクセスクラスの開発・テストを行う場合は、使用する DBMS をインストールしてください。 -- SQL Server -(SQL Server のバージョンは任意です。また、エディションについては、Express Edition 以外もお使いいただけますが、サンプルアプリケーションに指定する接続文字列を修正する必要がありますので、ご注意ください) -- Oracle Database (Express Edition を含みます) -- IBM DB2 ... optional -- HiRDB ... optional -- MySQL -- PostgreSQL +- あらかじめ、Visual Studio (若しくは Visual Studio Code と .NET系の SDK と Extension)をインストールしておいてください。 + +- また、Open 棟梁がサポートしている DBMS 中から使用するものを準備してください。[LocalServicesOnDocker](https://github.com/NetDevInfraWGinOSSConsortium/LocalServicesOnDocker) が便利です。 + +- サポートしている データプロバイダは、[Touryo.Infrastructure.Public.Db](https://github.com/OpenTouryoProject/OpenTouryo/tree/develop/root/programs/CS/Frameworks/Infrastructure/Public/Db) から確認できます。 + +- 正式サポートされているデータプロバイダは「SQL/OLE/ODBC/ODP/MCN/NPG」です。 + +- 現在は除外されていますが「DB2/HiRDB/OracleClient」は雛形があるのでエージェントなどを活用してセルフ・サポートすることは可能です。 + +- 略号とADO.NETデータプロバイダの名前空間 + - SQL:Microsoft.Data.SqlClient + - OLE:System.Data.Odbc + - ODBC:System.Data.OleDb + - ODP:Oracle.ManagedDataAccess.Client + - MCN:MySql.Data.MySqlClient + - NPG:Npgsql + - DB2:IBM.Data.DB2 + - HiRDB:Hitachi.HiRDB + - OracleClient:System.Data.OracleClient ### Open 棟梁の配置 「root」フォルダを、C ドライブ直下にコピーしてください。C ドライブ直下以外にコピーすると、Windows のファイルパスの最大文字長の制限により、ビルドに失敗することがあります。 -### データプロバイダの取得と配置 -Open 棟梁が現在サポートしているデータベースと、対応するデータプロバイダは以下のとおりです。 - -- Oracle - - Oracle.DataAccess.dll ... optional - - Oracle.ManagedDataAccess.dll -- IBM DB2 - - IBM.Data.DB2.dll ... optional -- HiRDB - - x86: pddndp40.dll, pddndpcore40.dll ... optional - - x64: pddndp40x.dll, pddndpcore40x.dll ... optional -- MySQL - - MySql.Data.dll -- PostgreSQL - - Npgsql.dll - ### サンプルデータベースのセットアップ + +#### [LocalServicesOnDocker](https://github.com/NetDevInfraWGinOSSConsortium/LocalServicesOnDocker)を活用 + #### SQL Server サンプルアプリケーションの実行には、Northwind データベースが必要です。 以下のマイクロソフトのサイトから、Northwind データベースのセットアップ スクリプトをダウンロードし、インストールしてください。 @@ -87,418 +65,77 @@ exec sp_dboption 'Northwind','select into/bulkcopy','true' - C:\root\files\resource\Sql\\[DBMS 名]\TestTable.txt を実行し、テスト用のテーブルを作成してください。 ### プログラムのビルド -Open 棟梁のプログラムをビルドするときは、**初回のみ、MSBuild を使用したビルドバッチファイルを実行**して、プログラムをビルドします。 -これは、Open 棟梁のテンプレート・ベースには、「フレームワーク部分 (ベースクラス1,2)」と「サンプルアプリケーション」がありますが、フレームワーク部分のビルド生成物 (DLL ファイル) を Open 棟梁の既定の置き場にコピーするなどの処理が必要なためです。 -これらの一連のビルドプロセスをまとめたバッチファイルを実行します。 - -ビルドバッチファイルは、以下のフォルダにあります。 -- C:\root\programs\CS -- C:\root\programs\VB - -`0_ExecAllBat.bat` を実行すると、必要なバッチファイルをまとめて実行することができます。下の表を参考に、実行する必要のあるバッチファイルをご確認いただき、必要に応じて `0_ExecAllBat.bat` をカスタマイズした上で実行してください。 - -<table Border="1"> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">#</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">バッチファイル名</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="1" rowspan="2">説明</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;" colspan="2" rowspan="1">存在</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">C#</td> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">VB</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">1</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">0_ExecAllBat.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">以下のファイルを使用してバッチビルドを行う。必要に応じてカスタマイズしてください。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">2</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">1_DeleteDir.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">ビルドによってできたフォルダを削除 (クリーンアップ) する。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">3</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">1_DeleteFile.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">一時ファイルなどを削除 (クリーンアップ) する。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">4</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net45.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.5.2 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">5</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net46.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.6 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">6</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net47.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.7 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">7</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_net48.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.8 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">8</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_netstd20.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Standard 2.0 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">9</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_netstd21.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Standard 2.1 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore30.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Core 3.0 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore50.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 5 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">10</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">2_Build_NuGet_nettcore60.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 6 をターゲットとする NuGet パッケージの作成用に、フレームワーク (ベースクラス1, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*1, *3</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">11</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net45.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.5.2 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">12</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net46.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.6 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">13</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net47.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.7 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">14</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_net48.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.8 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">15</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net45.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.5.2 をターゲットとする Business名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">16</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net46.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.6 をターゲットとする Business名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">17</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net47.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.7 をターゲットとするBusiness名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">18</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_net48.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Framework 4.8 をターゲットとするBusiness名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*2</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">19</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore20.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Core 2.0 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore30.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Core 3.0 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore50.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 5 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">20</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_Business_netcore60.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 6 をターゲットとする Business名前空間のフレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore30.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Core 3.0 をターゲットとする Business名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore50.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 5 をターゲットとする Business名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">21</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">3_Build_BusinessRichClient_netcore60.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET 6 をターゲットとする Business名前空間のリッチクライアント用フレームワーク (ベースクラス2, ライブラリ部分) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*2, *3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">22</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_CopyAssemblies.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">上記ビルドのプライマリ出力を参照先フォルダにコピーする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">23</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_Framework_Tool.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースの付属ツールをビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">24</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">4_Build_Framework_ToolCore.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースの付属ツールをビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">25</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_Bat_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースのサンプルアプリ (バッチ) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">26</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_BatCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースのサンプルアプリ (バッチ) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">27</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_2CS_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースのサンプルアプリ (2 層 C/S) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">28</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">5_Build_2CSCore_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースのサンプルアプリ (2 層 C/S) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">29</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">6_Build_WSSrv_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースのサンプルアプリ (Web サービス (サーバー側ロジック)) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">30</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">6_Build_WSSrvCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースのサンプルアプリ (Web サービス (サーバー側ロジック)) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">31</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">7_Build_Framework_WS.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースのフレームワーク (サービスインタフェース部分) をビルドする。 </td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">32</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">7_Build_Framework_WSCore.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースのフレームワーク (サービスインタフェース部分) をビルドする。 </td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">33</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">8_Build_WSClnt_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Frameworkベースのサンプルアプリ (Web サービスクライアント) をビルドする。</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">34</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">8_Build_WSClntCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">.NET Coreベースのサンプルアプリ (Web サービスクライアント) をビルドする。</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">35</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">10_Build_WebApp_sample.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">サンプルWebアプリ (ASP.NET) をビルドする。 </td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;" colspan="2" rowspan="1">○*4</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">36</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">10_Build_WebAppCore_sample.bat</td> -<Td style="background-color:#F8CBAD;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">サンプルWebアプリ (ASP.NET Core) をビルドする。 </td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○*3, *4</td> -<Td style="background-color:#F8CBAD;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">37</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">99_BuildLibsAtOtherRepos.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">当該リポジトリのBusiness名前空間を他のリポジトリで利用する際のバッチ(OpenTouryoTemplates - master ブランチ用)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">38</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">99_BuildLibsAtOtherReposInTimeOfDev.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">当該リポジトリのBusiness名前空間を他のリポジトリで利用する際のバッチ(OpenTouryo - develop ブランチ用)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">39</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">以下のテストコードのバッチビルドと実行を行う。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">40</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_Public.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">以下のPublic名前空間のテストコードのビルドと実行を行う。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">41</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecCUI.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Public.Security名前空間のCUIテストコードのビルドと実行を行う。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">42</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecCUI.sh</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Public.Security名前空間のCUIテストコードのビルドと実行を行う(WSL用)。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">43</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">y_Build_TestCode_SecGUI.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">Public.Security名前空間のGUIテストコードのビルドと実行を行う。</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">44</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net45.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">NuGet パッケージの作成時に、packages.config切り替えるバッチ(.NET Framework 4.5.2)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">45</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net46.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">NuGet パッケージの作成時に、packages.config切り替えるバッチ(.NET Framework 4.6)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">46</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net47.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">NuGet パッケージの作成時に、packages.config切り替えるバッチ(.NET Framework 4.7)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">47</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_ChangePackages_net48.bat</td> -<Td style="background-color:#C6E0B4;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">NuGet パッケージの作成時に、packages.config切り替えるバッチ(.NET Framework 4.8)</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#C6E0B4;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">-</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">48</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_Common.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">共通設定 (MSBuild 用)</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -<tr> -<Td style="background-color:#9BC2E6;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;font-weight:bold;">49</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">z_Common2.bat</td> -<Td style="background-color:#FFFFFF;text-align:left;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">共通設定 (Visual Studio 用) </td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -<Td style="background-color:#FFFFFF;text-align:center;color:#000000;font-family:'MS Pゴシック';font-size:11pt;">○</td> -</tr> -</table> - -<div style="font-size: small"> - <span style="color: red;">*1</span> NuGetパッケージを作成を作成する場合は必須<br /> - <span style="color: red;">*2</span> リッチクライアント アプリケーションを作成する場合は必須<br /> - <span style="color: red;">*3</span> .NET Standard、.NET Core ベースのアプリケーションを開発する場合は必須<br /> - <span style="color: red;">*4</span> 実際のアプリケーションの形態に応じて選択してください -</div> - -- 必要であれば、環境に合わせて、z_Common.bat 内の BUILDFILEPATH を書き換えてください。 +- Open 棟梁のプログラムをビルドするときは、ビルドバッチファイルを実行してビルドします。 + +- ビルドバッチファイルは、以下のフォルダにあります。 + - C:\root\programs\ + - C:\root\programs\CS + - C:\root\programs\VB + +#### ビルドバッチの構成 + +ビルドバッチは**ファイル名の先頭の番号がビルド順**を表しています。 +番号の小さいものから順に、基盤 → ツール → サンプルの順で積み上がる構成です。 + +| 番号 | 役割 | +|---|---| +| `0_` | 一括実行(`0_ExecAllBat.bat` が以下を順に呼び出します) | +| `1_` | クリーン(`bin` / `obj` / `packages` などの削除) | +| `2_` | フレームワーク本体(NuGet パッケージ化の対象となるアセンブリ) | +| `3_` | Business 層(業務コードの親クラス/テンプレート) | +| `4_` | 参照用アセンブリのコピー、付属ツール | +| `5_` `6_` `8_` `10_` | 各種サンプルアプリケーション | +| `7_` | Web サービスの受け口(フレームワーク側) | +| `9_` | (C# 側では未使用。VB 側で WPF クライアントに使用) | +| `y_` | 単体テストのコード | +| `z_` | 共通処理(各バッチの先頭から呼ばれます。単体では実行しません) | + +- **`0_ExecAllBat.bat` を実行すれば、基盤からサンプルまでが一括でビルドされます。** + 個別のバッチは、一部だけを作り直したいときに使います。 +- **`y_`(単体テスト)は `0_ExecAllBat.bat` に含まれません。** 単体テストを動かす場合は、 + 後述の `2_RunAllTests.ps1` を使うか、`y_` のバッチを個別に実行します。 +- ファイル名に `Core` が付くもの、または `netcore100` を含むものが .NET 10.0 向け、 + 付かないもの(`net48`)が .NET Framework 4.8 向けです。 +- `1_` のクリーンは**繰り返し実行されます**。基盤とサンプルを別々のタイミングで + 作り直すためで、このため全体をビルドし終えた時点では、 + 最後にビルドされたもの以外の中間生成物は残りません。 + +#### 共通処理(z_Common.bat) + +- 各バッチは先頭で `z_Common.bat` を呼び、次を用意します。 + - **ビルドツールの解決** … `vswhere` で MSBuild を探します(エディションに依存しません) + - **ビルド構成** … `BUILD_CONFIG`(Debug / Release)と `DEBUG_TYPE` + - **NuGet の設定** … プロキシ、および復元時に使う MSBuild の明示 + +- `z_Common2.bat` は同じ役割の **devenv 版**です。MSBuild では通らないが + devenv なら通る、というケースに備えて残されているもので、通常は使いません。 - Open 棟梁 が利用するライブラリは、NuGet 経由でダウンロードします。このため、プロキシ環境では、正常に NuGet ライブラリがダウンロードできないことがあります。プロキシ環境をお使いの場合は、以下のように http_proxy 環境変数を定義してください。 - C:\root\programs\CS\z_Common.bat および C:\root\programs\VB\z_Common.bat を、テキストエディタで開きます。 - 既定では、http_proxy 環境変数の定義部分はコメントアウトされていますので、"@rem" を削除して、このコメントを解除します。 - http_proxy 環境変数に、お使いのプロキシ情報を設定してください。 -- ビルド時に以下のエラーが発生した場合は、Windows 8 用の Windows SDK をインストールしてください。([Open 棟梁の issue](https://github.com/OpenTouryoProject/OpenTouryoTemplates/issues/48#issuecomment-241349223) が参考になります。) -``` -C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2863,5): error MSB3086: タスクは SdkToolsPath "" またはレジストリ キー "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0A\WinSDK-NetFx40Tools-x86" を使用して "AL.exe"を見つけられませんでした。SdkToolsPath が設定されていること、SdkToolsPath の下の適切なプロセッサ固有の場所にツールが存在すること、および Microsoft Windows SDK がインストールされていることを確認してください。 [C:\root\programs\CS\Frameworks\Infrastructure\Public\Public.csproj] +#### ビルド後の検証 + +ビルドが通ることの確認、単体テスト、サンプルの疎通確認は、 +`C:\root\programs\` にあるスクリプトで行えます。いずれも**終了コードで合否が分かります**。 + +```powershell +cd C:\root\programs +.\0_RunAll.ps1 # 下記 3 本をまとめて実行 ``` - + +| スクリプト | 内容 | +|---|---| +| `1_BuildAll.ps1` | 全ビルド(`0_ExecAllBat.bat` 相当)。エラー・警告を集約して判定 | +| `2_RunAllTests.ps1` | 単体テストを実行し、結果を前回のものと比較 | +| `3_SmokeTest.ps1` | サンプルアプリケーションを起動して疎通を確認 | + +手順と判定基準は、同じフォルダの +[`BUILDING.md`](programs/BUILDING.md) / [`TESTING.md`](programs/TESTING.md) / +[`SMOKETEST.md`](programs/SMOKETEST.md) を参照してください。 +リリース時の作業全体は [`RELEASE.md`](programs/RELEASE.md) にまとめています。 + ### ASP.NET 状態サービスの準備 管理者としてコマンドプロンプトを起動し、下記コマンドを実行します。 ```bat @@ -542,24 +179,17 @@ C:\root\programs\CS\Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSC ### .NET Core アプリケーション +**VB 版は、現時点で .NET Core 版の提供予定はありません。** 以下はいずれも C# のみです。 + #### 基盤: -- C# - - C:\root\programs\CS\Frameworks\Infrastructure - - C:\root\programs\CS\Frameworks\Infrastructure\ServiceInterface\ASPNETWebServiceCore -- VB -... +- C:\root\programs\CS\Frameworks\Infrastructure +- C:\root\programs\CS\Frameworks\Infrastructure\ServiceInterface\ASPNETWebServiceCore #### ツール: -- C# - - C:\root\programs\CS\Frameworks\Tools -- VB -... +- C:\root\programs\CS\Frameworks\Tools #### Sample アプリケーション: -- C# - - C:\root\programs\CS\Samples4NetCore -- VB -... +- C:\root\programs\CS\Samples4NetCore ## その他 特記事項 @@ -571,9 +201,6 @@ C:\root\programs\CS\Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSC ご利用いただく中で、バグを発見されましたら、[issue](https://github.com/OpenTouryoProject/OpenTouryo/issues) としてご連絡ください。 コミュニティで内容を確認し、適切に対応いたします。 -### NuGetパッケージの作成方法 -Open 棟梁の NuGetパッケージを作成する方法については、[こちらの記事](https://github.com/OpenTouryoProject/OpenTouryo/wiki/HowToCreateOpenTouryoNuGetPackages.ja)をご参照ください。 - ### ライブラリの入手、輸出手続き、使用許諾への添付について - NuGetまたはnpmなどのパッケージ・マネージャーから取得できるライブラリは、Open 棟梁に同梱されないため、輸出管理する必要はありません。 - これ以外のライブラリ、つまりパッケージ・マネージャーから入手できないライブラリは、必要に応じて自身で入手・同梱して輸出する必要があります。この場合、Open棟梁のライセンスに、使用するライブラリのライセンスを添付する必要があります。 diff --git a/root/programs/0_RunAll.ps1 b/root/programs/0_RunAll.ps1 new file mode 100644 index 000000000..14e6e7f12 --- /dev/null +++ b/root/programs/0_RunAll.ps1 @@ -0,0 +1,31 @@ +# --- 処理部:他のps1ファイルを順次実行 --- +# ※ ダブル クリック起動でもカレント ディレクトリに依存しないよう $PSScriptRoot を使う。 +# ※ 順序は固定(RELEASE.md 3 節)。1 のクリーンとアセンブリ配置が 2・3 の前提になる。 +$scripts = @("1_BuildAll.ps1", "2_RunAllTests.ps1", "3_SmokeTest.ps1") +$results = @() + +foreach ($s in $scripts) +{ + & (Join-Path $PSScriptRoot $s) + $results += [pscustomobject]@{ スクリプト = $s; 終了コード = $LASTEXITCODE } +} + +# --- 結果のまとめ --- +Write-Host "" +Write-Host "================ 全体のまとめ ================" +$results | Format-Table -AutoSize | Out-String | Write-Host + +# 1_BuildAll.ps1 は既知の署名エラー(MSB3482)で 1 になることがある。 +# 終了コードだけで判断せず、エラー一覧の内容を確認すること(RELEASE.md 3 節)。 +$ng = @($results | Where-Object { $_.終了コード -ne 0 }) +if ($ng.Count -eq 0) +{ + Write-Host "すべて OK です。" -ForegroundColor Green +} +else +{ + Write-Host ("{0} 本が 0 以外で終了しました。上のログを確認してください。" -f $ng.Count) -ForegroundColor Yellow +} + +# --- 画面を残すための処理 --- +Read-Host "`nEnterキーを押すとウィンドウを閉じます" diff --git a/root/programs/1_BuildAll.ps1 b/root/programs/1_BuildAll.ps1 new file mode 100644 index 000000000..1d0987638 --- /dev/null +++ b/root/programs/1_BuildAll.ps1 @@ -0,0 +1,259 @@ +<# +.SYNOPSIS + 全ビルド(0_ExecAllBat.bat 相当)を実行し、エラー・警告を集約して合否を判定する。 + +.DESCRIPTION + リリース時の「build バッチで全ビルドが通ることを確認」を機械化したもの(#513 段階 2)。 + + 既存のビルド バッチをそのまま呼び出し、出力を解析して結果を集約する。 + 「何をビルドするか」の正はバッチ側に残し、本スクリプトは実行と判定のみを担う。 + + <なぜラッパーが必要か> + ・各バッチは MSBuild の終了コードを伝播しない(%ERRORLEVEL% を見ていない) + ・各バッチの末尾に pause があり、対話入力を待つ + ・-v:d(詳細)で出力が膨大なため、目視での確認が難しい + このため、stdin を与えて実行し、出力から error / warning を抽出して判定する。 + +.PARAMETER Only + ステップ名の部分一致で対象を絞る(例: -Only "net48")。動作確認用。 + +.PARAMETER SkipClean + クリーン処理(1_DeleteDir / 1_DeleteFile)を省略する。 + ※ リリース判定では省略しないこと。前回のビルド成果物が残っていると、 +   ビルドが通ったように見えることがある。 + +.PARAMETER OutputDir + 各ステップの出力ログの保存先。既定は %TEMP%\OpenTouryoBuildLogs。 + +.EXAMPLE + .\1_BuildAll.ps1 + +.EXAMPLE + .\1_BuildAll.ps1 -Only "Framework_Tool" -SkipClean + +.NOTES + 作成者 :玄人 幸道 + 更新履歴 : + 日時 更新者 内容 + ---------- ---------------- ------------------------------------------------- + 2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化) +#> +[CmdletBinding()] +param( + [string]$Only, + [switch]$SkipClean, + [string]$OutputDir = (Join-Path $env:TEMP "OpenTouryoBuildLogs") +) + +# 本スクリプトは root\programs に置き、C# 側(root\programs\CS)を対象とする。 +# ビルド バッチはすべて CS 直下にあるため、そこを起点にする。 +$csRoot = Join-Path $PSScriptRoot "CS" +New-Item -ItemType Directory -Force $OutputDir | Out-Null + +# ------------------------------------------------------------------ +# コンソールのコード ページを先に UTF-8 にしておく +# ------------------------------------------------------------------ +# z_Common.bat は先頭で chcp 65001 を実行する。コード ページはコンソール +# 全体の設定なので、子プロセスで変えても呼び出し元の画面に影響する。 +# 日本語環境の既定は 932 で、932 → 65001 の切り替わりで画面が再描画され、 +# **それまでに表示したステップの結果が消える**。 +# +# z_Common.bat を最初に呼ぶのは 2_Build_NuGet_net48.bat(3 ステップ目)なので、 +# 何も表示していない今のうちに切り替えておけば、実行中は変化しない。 +# +# 元に戻さないのは、戻す操作でも再描画が起きてサマリが消えるため。 +# 各ビルド バッチも 65001 にしたまま終了するので、挙動は従来と同じ。 +if ((cmd /c chcp) -notmatch '65001') +{ + cmd /c chcp 65001 | Out-Null +} + +# コンソールのコード ページとは別に、PowerShell 側の出力エンコードも合わせる。 +# Windows PowerShell 5.1 は起動時の値を保持しており、実行中にコード ページが +# 変わっても追随しない。ここを合わせないと、バッチ(UTF-8 で出力)の内容を +# 旧コード ページで解釈してしまい、ログとエラー一覧が文字化けする。 +# ※ 2 回目以降の実行ではコード ページが既に 65001 で上の分岐を通らないため、 +# この処理は分岐の外に置く必要がある。 +if ([Console]::OutputEncoding.CodePage -ne 65001) +{ + [Console]::OutputEncoding = New-Object Text.UTF8Encoding $false +} + +# ------------------------------------------------------------------ +# ビルド ステップの定義(0_ExecAllBat.bat と同じ順序・同じ内容) +# ------------------------------------------------------------------ +# Clean = $true のものは -SkipClean で省略される。 +$steps = @( + # --- net48 : 基盤 --- + @{ Name = "Clean (net48 基盤)"; Bat = "1_DeleteDir.bat"; Clean = $true } + @{ Name = "Clean files (net48 基盤)"; Bat = "1_DeleteFile.bat"; Clean = $true } + @{ Name = "NuGet (net48)"; Bat = "2_Build_NuGet_net48.bat" } + @{ Name = "Business (net48)"; Bat = "3_Build_Business_net48.bat" } + @{ Name = "Business.RichClient (net48)"; Bat = "3_Build_BusinessRichClient_net48.bat" } + + # --- netcore100 : 基盤 --- + @{ Name = "Clean (core 基盤)"; Bat = "1_DeleteDir.bat"; Clean = $true } + @{ Name = "Clean files (core 基盤)"; Bat = "1_DeleteFile.bat"; Clean = $true } + @{ Name = "NuGet (netcore100)"; Bat = "2_Build_NuGet_netcore100.bat" } + @{ Name = "Business (netcore100)"; Bat = "3_Build_Business_netcore100.bat" } + @{ Name = "Business.RichClient (core)"; Bat = "3_Build_BusinessRichClient_netcore100.bat" } + + # --- 参照用アセンブリのコピー --- + @{ Name = "CopyAssemblies"; Bat = "4_Build_CopyAssemblies.bat" } + + # --- net48 : ツールとサンプル --- + @{ Name = "Clean (net48 サンプル)"; Bat = "1_DeleteDir.bat"; Clean = $true } + @{ Name = "Clean files (net48 サンプル)"; Bat = "1_DeleteFile.bat"; Clean = $true } + @{ Name = "Framework_Tool (net48)"; Bat = "4_Build_Framework_Tool.bat" } + @{ Name = "2CS_sample (net48)"; Bat = "5_Build_2CS_sample.bat" } + @{ Name = "Bat_sample (net48)"; Bat = "5_Build_Bat_sample.bat" } + @{ Name = "CLI_sample (net48)"; Bat = "5_Build_CLI_sample.bat" } + @{ Name = "WSSrv_sample (net48)"; Bat = "6_Build_WSSrv_sample.bat" } + @{ Name = "Framework_WS (net48)"; Bat = "7_Build_Framework_WS.bat" } + @{ Name = "WSClnt_sample (net48)"; Bat = "8_Build_WSClnt_sample.bat" } + @{ Name = "WebApp_sample (net48)"; Bat = "10_Build_WebApp_sample.bat" } + + # --- netcore100 : ツールとサンプル --- + @{ Name = "Clean (core サンプル)"; Bat = "1_DeleteDir.bat"; Clean = $true } + @{ Name = "Clean files (core サンプル)"; Bat = "1_DeleteFile.bat"; Clean = $true } + @{ Name = "Framework_ToolCore"; Bat = "4_Build_Framework_ToolCore.bat" } + @{ Name = "2CSCore_sample"; Bat = "5_Build_2CSCore_sample.bat" } + @{ Name = "BatCore_sample"; Bat = "5_Build_BatCore_sample.bat" } + @{ Name = "CLICore_sample"; Bat = "5_Build_CLICore_sample.bat" } + @{ Name = "WSSrvCore_sample"; Bat = "6_Build_WSSrvCore_sample.bat" } + @{ Name = "Framework_WSCore"; Bat = "7_Build_Framework_WSCore.bat" } + @{ Name = "WSClntCore_sample"; Bat = "8_Build_WSClntCore_sample.bat" } + @{ Name = "WebAppCore_sample"; Bat = "10_Build_WebAppCore_sample.bat" } +) + +# ------------------------------------------------------------------ +# 出力の解析 +# ------------------------------------------------------------------ +# MSBuild のエラー・警告行は「: error CS1002:」のような形式で、 +# コード部分はロケールによらないため、これを抽出する。 +# ("ビルドに成功しました" 等のサマリ文言は日本語環境で変わるため使わない) +# +# ※ コードを伴わない「: error :」形式もある。 +#   例: NuGet の restore 失敗 +#   Microsoft.NuGet.targets(198,5): error : Your project does not reference ... +#   このためコード部分は省略可能として扱う。 +function Get-Diagnostics([string[]]$lines) +{ + $errors = New-Object System.Collections.Generic.List[string] + $warnings = New-Object System.Collections.Generic.List[string] + + foreach ($line in $lines) + { + if ($line -match ':\s*error(\s+[A-Za-z]+\d+)?\s*:') + { + $errors.Add($line.Trim()) + } + elseif ($line -match ':\s*warning(\s+[A-Za-z]+\d+)?\s*:') + { + $warnings.Add($line.Trim()) + } + elseif ($line -match '^\s*\[ERROR\]') + { + # z_Common.bat が MSBuild 未検出時に出力する独自のエラー + $errors.Add($line.Trim()) + } + } + + # 同一の指摘が複数プロジェクトから重複して出るため、一意化する。 + return [pscustomobject]@{ + Errors = @($errors | Select-Object -Unique) + Warnings = @($warnings | Select-Object -Unique) + } +} + +# ------------------------------------------------------------------ +# 実行 +# ------------------------------------------------------------------ +Push-Location $csRoot +$results = @() +$allErrors = New-Object System.Collections.Generic.List[string] +$total = [Diagnostics.Stopwatch]::StartNew() + +foreach ($s in $steps) +{ + if ($Only -and ($s.Name -notlike "*$Only*") -and ($s.Bat -notlike "*$Only*")) + { + continue + } + if ($SkipClean -and $s.Clean) + { + continue + } + + $bat = Join-Path $csRoot $s.Bat + if (-not (Test-Path $bat)) + { + Write-Host (" [{0}] バッチが見つかりません : {1}" -f $s.Name, $s.Bat) -ForegroundColor Red + $results += [pscustomobject]@{ ステップ = $s.Name; 結果 = "バッチ無し"; エラー = "-"; 警告 = "-"; 秒 = "-" } + continue + } + + Write-Host ("=== {0} ===" -f $s.Name) -ForegroundColor Cyan + + $safe = ($s.Name -replace '[^A-Za-z0-9]', '_') + $log = Join-Path $OutputDir "$safe.log" + $sw = [Diagnostics.Stopwatch]::StartNew() + + # 各バッチは末尾に pause を持つため、stdin を与えて実行する + # (0_ExecAllBat.bat の "echo | call ..." と同じ方式)。 + cmd /c "echo. | call `"$bat`"" *>&1 | Out-File $log -Encoding UTF8 + $sw.Stop() + + $diag = Get-Diagnostics (Get-Content $log -EA SilentlyContinue) + + foreach ($e in $diag.Errors) { $allErrors.Add(("[{0}] {1}" -f $s.Name, $e)) } + + $verdict = if ($diag.Errors.Count -eq 0) { "OK" } else { "NG" } + $color = if ($verdict -eq "OK") { "Green" } else { "Red" } + Write-Host (" {0} エラー {1} / 警告 {2} ({3:N1} 秒)" -f ` + $verdict, $diag.Errors.Count, $diag.Warnings.Count, $sw.Elapsed.TotalSeconds) -ForegroundColor $color + + $results += [pscustomobject]@{ + ステップ = $s.Name + 結果 = $verdict + エラー = $diag.Errors.Count + 警告 = $diag.Warnings.Count + 秒 = [Math]::Round($sw.Elapsed.TotalSeconds, 1) + } +} + +$total.Stop() +Pop-Location + +# ------------------------------------------------------------------ +# サマリ +# ------------------------------------------------------------------ +Write-Host "" +Write-Host "================ サマリ ================" +$results | Format-Table -AutoSize | Out-String | Write-Host +Write-Host (" 所要時間 : {0:N1} 分" -f $total.Elapsed.TotalMinutes) +Write-Host (" ログ : {0}" -f $OutputDir) + +if ($allErrors.Count -gt 0) +{ + Write-Host "" + Write-Host "================ エラー一覧 ================" -ForegroundColor Red + $allErrors | Select-Object -First 30 | ForEach-Object { Write-Host (" " + $_) } + if ($allErrors.Count -gt 30) + { + Write-Host (" ... 他 {0} 件(詳細はログを参照)" -f ($allErrors.Count - 30)) + } +} + +$ng = @($results | Where-Object { $_.結果 -ne "OK" }) +Write-Host "" +if ($ng.Count -eq 0) +{ + Write-Host " 全ステップ OK" -ForegroundColor Green + exit 0 +} +else +{ + Write-Host (" {0} ステップが NG" -f $ng.Count) -ForegroundColor Red + exit 1 +} diff --git a/root/programs/2_RunAllTests.ps1 b/root/programs/2_RunAllTests.ps1 new file mode 100644 index 000000000..ad64d2fa4 --- /dev/null +++ b/root/programs/2_RunAllTests.ps1 @@ -0,0 +1,323 @@ +<# +.SYNOPSIS + 単体テストのビルド バッチを実行し、再生成された結果ファイルを HEAD と比較して合否を一覧する。 + +.DESCRIPTION + リリース時の「単体テスト スクリプトの実行結果を diff で目視」を機械化したもの(#513 段階 1)。 + + <既存の運用> + y_Build_TestCode*.bat は「ビルド → テスト実行 → 結果を Result*.txt へ出力」まで行う。 + この Result*.txt は Git 管理下にあり、バッチを実行すると上書きされる。 + すなわち従来の手順は次のとおりだった。 + + 1. バッチを実行して Result*.txt を再生成する + 2. git diff で「前回のリリース時の結果」との差分を目視する + + <本スクリプト> + 同じ構造のまま、2 の目視を機械比較に置き換える。 + + 期待値 : HEAD にコミットされている Result*.txt(git show で取得) + 実測値 : バッチが再生成したワーキング ツリーの Result*.txt + + 比較は CompareResult.ps1 が行い、実行ごとに変わる値(日時・処理時間・ + スレッド ID・パス・署名値等)を正規化してから差分を取る。 + + <ビルドをバッチに委ねている理由> + csproj / sln を直接 msbuild すると、nuget.exe restore が行うネイティブ DLL の + 配置(Microsoft.Data.SqlClient.SNI 等)が漏れ、実行時に DllNotFoundException になる。 + 「何をどうビルドするか」の正はバッチ側に置く。 + + <前提> + ・Frameworks をビルド済み(Build_net48 / Build_netcore100 が存在すること) + ・SQL Server の Northwind に接続できること(TestBatch が使用) + + <副作用> + ワーキング ツリーの Result*.txt が書き換わる。これは従来のバッチ運用と同じで、 + 内容の検収(コミットするか戻すか)は人が git diff で判断する。 + +.PARAMETER OutputDir + HEAD 版の期待値とビルド ログの出力先。既定は %TEMP%\OpenTouryoTestResults。 + +.PARAMETER SkipBuild + バッチの実行を省略し、ワーキング ツリーにある既存の Result*.txt を比較する。 + +.EXAMPLE + .\2_RunAllTests.ps1 + +.EXAMPLE + .\2_RunAllTests.ps1 -SkipBuild + +.NOTES + 作成者 :玄人 幸道 + 更新履歴 : + 日時 更新者 内容 + ---------- ---------------- ------------------------------------------------- + 2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化) +#> +[CmdletBinding()] +param( + [string]$OutputDir = (Join-Path $env:TEMP "OpenTouryoTestResults"), + [switch]$SkipBuild +) + +$ErrorActionPreference = "Continue" + +# ------------------------------------------------------------------ +# カレント ディレクトリからの実行を許可する +# ------------------------------------------------------------------ +# PowerShell は子プロセスに NoDefaultCurrentDirectoryInExePath=1 を渡す。 +# 一方 y_Build_TestCode*.bat は、出力フォルダへ cd したうえで +# SimpleBatch.exe /Dap SQL ... +# のようにパス区切りを含まない名前で実行するため、この変数が効いていると +# 'SimpleBatch.exe' is not recognized as an internal or external command +# となり、結果ファイルが空になる(バッチ自体は成功扱いで進む)。 +# バッチを直接ダブル クリックした場合と同じ条件にするため、ここで解除する。 +Remove-Item Env:\NoDefaultCurrentDirectoryInExePath -EA SilentlyContinue + +# 本スクリプトは root\programs に置き、C# 側(root\programs\CS)を対象とする。 +$progRoot = $PSScriptRoot +# ビルド バッチ(y_Build_TestCode*.bat)が置かれている root\programs\CS +$csRoot = Join-Path $progRoot "CS" +# 単体テストのプロジェクトと結果ファイルが置かれている場所 +$testsRoot = Join-Path $csRoot "Frameworks\Tests" +$repoRoot = (& git -C $testsRoot rev-parse --show-toplevel) +New-Item -ItemType Directory -Force $OutputDir | Out-Null + +# ------------------------------------------------------------------ +# コンソールのコード ページを先に UTF-8 にしておく +# ------------------------------------------------------------------ +# ビルド バッチが呼ぶ z_Common.bat は先頭で chcp 65001 を実行する。 +# コード ページはコンソール全体の設定なので、子プロセスで変えても +# 呼び出し元の画面に影響し、日本語環境の既定 932 からの切り替わりで +# 画面が再描画されて**それまでの表示が消える**。 +# 何も表示していない今のうちに切り替えておけば、実行中は変化しない。 +# 戻さないのは、戻す操作でも再描画が起きてサマリが消えるため。 +if ((cmd /c chcp) -notmatch '65001') +{ + cmd /c chcp 65001 | Out-Null +} + +# コンソールのコード ページとは別に、PowerShell 側の出力エンコードも合わせる。 +# Windows PowerShell 5.1 は起動時の値を保持しており、実行中にコード ページが +# 変わっても追随しない。ここを合わせないと、バッチ(UTF-8 で出力)の内容を +# 旧コード ページで解釈してしまい、ログとエラー一覧が文字化けする。 +# ※ 2 回目以降の実行ではコード ページが既に 65001 で上の分岐を通らないため、 +# この処理は分岐の外に置く必要がある。 +if ([Console]::OutputEncoding.CodePage -ne 65001) +{ + [Console]::OutputEncoding = New-Object Text.UTF8Encoding $false +} + +# ------------------------------------------------------------------ +# テスト証明書の配置 +# ------------------------------------------------------------------ +# EncAndDecUtilCUI の csproj は *.cer / *.pfx を CopyToOutputDirectory しているため、 +# これらが無いとビルドが MSB3030 で失敗する。 +# y_Build_TestCode_SecCUI.bat も copy_cert.bat を呼ぶが、そちらは C:\root\files\... を +# 参照するため、リポジトリだけを clone した環境では配置できない。 +# ここではリポジトリ内の正本(root/files/resource/X509/)から補う。 +function Copy-TestCertificates +{ + $destDir = Join-Path $testsRoot "EncAndDecUtilCUI" + $srcDir = Join-Path $testsRoot "..\..\..\..\files\resource\X509" + + if (-not (Test-Path $srcDir)) + { + Write-Host " 証明書の正本フォルダが見つかりません : $srcDir" -ForegroundColor Yellow + return + } + + $names = @("SHA256RSA", "SHA256DSA", "SHA256ECDSA", "SHA384ECDSA", "SHA521ECDSA") + $copied = 0 + + foreach ($n in $names) + { + foreach ($ext in @("cer", "pfx")) + { + $dest = Join-Path $destDir "$n.$ext" + if (Test-Path $dest) { continue } + + $src = Join-Path $srcDir "$n.$ext" + if (Test-Path $src) + { + Copy-Item $src $dest -Force + $copied++ + } + else + { + Write-Host (" 証明書が見つかりません : {0}" -f $src) -ForegroundColor Yellow + } + } + } + + if ($copied -gt 0) + { + Write-Host (" テスト証明書を {0} 件配置しました。" -f $copied) + } +} + +# ------------------------------------------------------------------ +# テストの定義 +# ------------------------------------------------------------------ +# Result : バッチが再生成する結果ファイル(Tests からの相対パス) +# = 期待値でもある(HEAD 版と比較する) +# Bat : ビルドとテスト実行を行うバッチ(root\programs\CS 配下) +# SkipLog4net : log4net の内部トレースを比較対象から外すか +$tests = @( + @{ + Name = "TestCode (net48)"; Bat = "y_Build_TestCode_Public.bat" + Result = "TestCode\Result48.txt"; SkipLog4net = $false + } + @{ + Name = "TestCode (net10.0)"; Bat = "y_Build_TestCode_Public.bat" + Result = "TestCode\ResultCore100.txt"; SkipLog4net = $false + } + @{ + Name = "SimpleBatch (net48)"; Bat = "y_Build_TestCode_Batch.bat" + Result = "TestBatch\ResultSimpleBatch48.txt"; SkipLog4net = $true + } + @{ + Name = "SimpleBatch (net10.0)"; Bat = "y_Build_TestCode_Batch.bat" + Result = "TestBatch\ResultSimpleBatchCore100.txt"; SkipLog4net = $true + } + @{ + Name = "EncAndDecUtilCUI (net48)"; Bat = "y_Build_TestCode_SecCUI.bat" + Result = "EncAndDecUtilCUI\Result48.txt"; SkipLog4net = $false + } + @{ + Name = "EncAndDecUtilCUI (net10.0)"; Bat = "y_Build_TestCode_SecCUI.bat" + Result = "EncAndDecUtilCUI\ResultCore100.txt"; SkipLog4net = $false + } +) + +# ------------------------------------------------------------------ +# 期待値(HEAD 版)の取り出し +# ------------------------------------------------------------------ +# バッチがワーキング ツリーの Result*.txt を上書きするため、 +# 上書きされる前に HEAD の内容を退避しておく。 +# ※ git show は参照系のみ。ワーキング ツリーには一切触れない。 +Write-Host "=== 事前準備 ===" -ForegroundColor Cyan +Copy-TestCertificates + +$expectedOf = @{} + +foreach ($t in $tests) +{ + $full = Join-Path $testsRoot $t.Result + # git が扱えるようリポジトリ相対・スラッシュ区切りにする + $rel = ($full.Substring($repoRoot.Length).TrimStart('\','/') -replace '\\','/') + $safe = ($t.Name -replace '[^A-Za-z0-9]', '_') + $dst = Join-Path $OutputDir "expected_$safe.txt" + + # バイト列を保つため cmd のリダイレクトで受ける + # (PowerShell のパイプを経由すると再エンコードされる) + cmd /c "git -C `"$repoRoot`" show `"HEAD:$rel`" > `"$dst`" 2>nul" + + if ((Test-Path $dst) -and (Get-Item $dst).Length -gt 0) + { + $expectedOf[$t.Name] = $dst + } + else + { + Write-Host (" HEAD から取得できません : {0}" -f $rel) -ForegroundColor Yellow + } +} + +Write-Host (" 期待値(HEAD 版)を {0} 件退避しました。" -f $expectedOf.Count) + +# ------------------------------------------------------------------ +# ビルドとテスト実行 +# ------------------------------------------------------------------ +# 1 本のバッチが net48 版と .NET (Core) 版の両方をビルド・実行するため、 +# 同一バッチは 1 回だけ実行する。 +if (-not $SkipBuild) +{ + foreach ($bat in ($tests | ForEach-Object { $_.Bat } | Select-Object -Unique)) + { + Write-Host "" + Write-Host ("=== ビルドと実行 : {0} ===" -f $bat) -ForegroundColor Cyan + + $path = Join-Path $csRoot $bat + if (-not (Test-Path $path)) + { + Write-Host " バッチが見つかりません" -ForegroundColor Red + continue + } + + $log = Join-Path $OutputDir ("build_" + ($bat -replace '[^A-Za-z0-9]','_') + ".log") + $sw = [Diagnostics.Stopwatch]::StartNew() + + Push-Location $csRoot + # バッチ末尾の pause に対応するため stdin を与える。 + cmd /c "echo. | call `"$path`"" *>&1 | Out-File $log -Encoding UTF8 + Pop-Location + + $sw.Stop() + Write-Host (" 完了 ({0:N1} 秒) ログ : {1}" -f $sw.Elapsed.TotalSeconds, $log) + } +} + +# ------------------------------------------------------------------ +# 比較 +# ------------------------------------------------------------------ +$cmp = Join-Path $progRoot "CompareResult.ps1" +$results = @() + +foreach ($t in $tests) +{ + Write-Host "" + Write-Host ("=== {0} ===" -f $t.Name) -ForegroundColor Cyan + + $actual = Join-Path $testsRoot $t.Result + + if (-not $expectedOf.ContainsKey($t.Name)) + { + Write-Host " 期待値(HEAD 版)が無いため比較できません" -ForegroundColor Red + $results += [pscustomobject]@{ テスト = $t.Name; 結果 = "期待値無し"; 差分 = "-" } + continue + } + if (-not (Test-Path $actual)) + { + Write-Host " 結果ファイルが生成されていません" -ForegroundColor Red + $results += [pscustomobject]@{ テスト = $t.Name; 結果 = "結果無し"; 差分 = "-" } + continue + } + + # CompareResult.ps1 は画面表示に Write-Host を使うため、 + # 件数は -PassThru のオブジェクトで受け取る。 + if ($t.SkipLog4net) + { + $cmpResult = & $cmp -Expected $expectedOf[$t.Name] -Actual $actual -SkipLog4netTrace -PassThru + } + else + { + $cmpResult = & $cmp -Expected $expectedOf[$t.Name] -Actual $actual -PassThru + } + + $results += [pscustomobject]@{ + テスト = $t.Name + 結果 = $cmpResult.Result + 差分 = $cmpResult.DiffCount + } +} + +# ------------------------------------------------------------------ +# サマリ +# ------------------------------------------------------------------ +Write-Host "" +Write-Host "================ サマリ ================" +$results | Format-Table -AutoSize | Out-String | Write-Host +Write-Host (" 期待値・ログ : {0}" -f $OutputDir) +Write-Host " 実測値 : ワーキング ツリーの Result*.txt(git diff で確認できます)" + +$ng = @($results | Where-Object { $_.結果 -ne "OK" }) +if ($ng.Count -eq 0) +{ + Write-Host " 全テスト OK" -ForegroundColor Green + exit 0 +} +else +{ + Write-Host (" {0} 件が NG" -f $ng.Count) -ForegroundColor Yellow + exit 1 +} diff --git a/root/programs/3_SmokeTest.ps1 b/root/programs/3_SmokeTest.ps1 new file mode 100644 index 000000000..224db9ea1 --- /dev/null +++ b/root/programs/3_SmokeTest.ps1 @@ -0,0 +1,754 @@ +<# +.SYNOPSIS + サンプル アプリを起動して疎通を確認し、合否を一覧する。 + +.DESCRIPTION + リリース時の「サンプルを幾つか見繕って手動で疎通を行う」を機械化したもの(#513 段階 3)。 + + <段階 1・2 との違い> + 段階 1(2_RunAllTests.ps1)は「出力が前回と同じか」を見る回帰テスト。 + 本スクリプトは「起動して、想定どおり動き、例外なく終わるか」を見る疎通テスト。 + 期待結果ファイルは持たず、判定条件を定義側に書く。 + + <対象> + 非 UI 系(バッチ・CLI)と Web 系(Web アプリ・Web サービス)。 + WinForms / WPF 系は UI Automation が必要で維持費が高いため対象外とし、 + リリース チェックリストの手作業項目として残す。 + + <ビルド> + リポジトリ既定のビルド バッチを呼ぶ。理由は 2_RunAllTests.ps1 と同じで、 + csproj を直接ビルドすると nuget.exe restore が行うネイティブ DLL の配置が漏れる。 + + なお 0_ExecAllBat.bat は途中で 1_DeleteDir.bat を繰り返し実行し、 + 配下の bin / obj を再帰的に削除する。このため 1_BuildAll.ps1 の完走後に + 残るのは最後にビルドされた Core サンプルだけで、net48 サンプルは残らない。 + 本スクリプトが自分でビルドするのはこのため。 + + <DB> + SQL Server の Northwind を使用する。 + RerunnableBatch 系は Orders(830 件) を読み Orders2 へ INSERT するため、 + 実行前に Orders2 を空にする必要がある。実行後は 830 件=初期状態に戻る。 + +.PARAMETER Only + 対象名の部分一致で絞る(例: -Only "Rerunnable")。 + +.PARAMETER SkipBuild + ビルドを省略し、既存のバイナリで疎通のみ行う。 + +.PARAMETER OutputDir + ログの保存先。既定は %TEMP%\OpenTouryoSmokeTest。 + +.EXAMPLE + .\3_SmokeTest.ps1 + +.EXAMPLE + .\3_SmokeTest.ps1 -Only "net48" -SkipBuild + +.NOTES + 作成者 :玄人 幸道 + 更新履歴 : + 日時 更新者 内容 + ---------- ---------------- ------------------------------------------------- + 2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化) +#> +[CmdletBinding()] +param( + [string]$Only, + [switch]$SkipBuild, + [string]$OutputDir = (Join-Path $env:TEMP "OpenTouryoSmokeTest") +) + +$ErrorActionPreference = "Continue" + +# ------------------------------------------------------------------ +# カレント ディレクトリからの実行を許可する +# ------------------------------------------------------------------ +# PowerShell は子プロセスに NoDefaultCurrentDirectoryInExePath=1 を渡すが、 +# ビルド バッチは出力フォルダへ cd したうえでパス区切りを含まない名前で +# 実行するため、これが効いていると exe を起動できない。 +# (TESTING.md の「PowerShell から .bat を呼ぶときの注意」と同じ) +Remove-Item Env:\NoDefaultCurrentDirectoryInExePath -EA SilentlyContinue + +# 本スクリプトは root\programs に置き、C# 側(root\programs\CS)を対象とする。 +# ビルド バッチもサンプルも CS 配下にあるため、そこを起点にする。 +$csRoot = Join-Path $PSScriptRoot "CS" +New-Item -ItemType Directory -Force $OutputDir | Out-Null + +# ------------------------------------------------------------------ +# コンソールのコード ページを先に UTF-8 にしておく +# ------------------------------------------------------------------ +# ビルド バッチが呼ぶ z_Common.bat は先頭で chcp 65001 を実行する。 +# コード ページはコンソール全体の設定なので、子プロセスで変えても +# 呼び出し元の画面に影響し、日本語環境の既定 932 からの切り替わりで +# 画面が再描画されて**それまでの表示が消える**。 +# 何も表示していない今のうちに切り替えておけば、実行中は変化しない。 +# 戻さないのは、戻す操作でも再描画が起きてサマリが消えるため。 +if ((cmd /c chcp) -notmatch '65001') +{ + cmd /c chcp 65001 | Out-Null +} + +# コンソールのコード ページとは別に、PowerShell 側の出力エンコードも合わせる。 +# Windows PowerShell 5.1 は起動時の値を保持しており、実行中にコード ページが +# 変わっても追随しない。ここを合わせないと、バッチ(UTF-8 で出力)の内容を +# 旧コード ページで解釈してしまい、ログとエラー一覧が文字化けする。 +# ※ 2 回目以降の実行ではコード ページが既に 65001 で上の分岐を通らないため、 +# この処理は分岐の外に置く必要がある。 +if ([Console]::OutputEncoding.CodePage -ne 65001) +{ + [Console]::OutputEncoding = New-Object Text.UTF8Encoding $false +} + +# ------------------------------------------------------------------ +# 接続文字列 +# ------------------------------------------------------------------ +# サンプルが実際に使う App.config から読む。 +# ここで別途ハードコードすると、サンプル側の変更に追随できなくなる。 +function Get-SampleConnectionString +{ + $config = Join-Path $csRoot "Samples\Bat_sample\SimpleBatch_sample\App.config" + if (-not (Test-Path $config)) { return $null } + + $xml = [xml](Get-Content $config -Raw) + $node = $xml.configuration.connectionStrings.add | + Where-Object { $_.name -eq "ConnectionString_SQL" } + return $node.connectionString +} + +$connString = Get-SampleConnectionString + +function Invoke-Sql([string]$sql) +{ + $c = New-Object System.Data.SqlClient.SqlConnection $connString + $c.Open() + try + { + $cmd = $c.CreateCommand() + $cmd.CommandText = $sql + return $cmd.ExecuteScalar() + } + finally { $c.Close() } +} + +# ------------------------------------------------------------------ +# 対象の定義 +# ------------------------------------------------------------------ +# Name : 表示名 +# Bat : ビルドに使うバッチ(root\programs\CS 配下) +# Exe : 実行ファイル(net48)。Dll を指定した場合は dotnet で実行する。 +# Args : コマンドライン引数 +# Pre : 実行前に行う準備(スクリプト ブロック) +# Expect : 標準出力がこの正規表現に一致すれば成功 +# Verify : 追加の検証(スクリプト ブロック)。$true を返せば成功 +# +# ※ サンプルは末尾に Console.ReadKey() を持つため、出力をリダイレクトすると +# 必ず例外で終わる。これはテスト内容とは無関係なので、判定から除外する。 +$batchArgs = @("/DAP", "SQL", "/MODE1", "individual", "/MODE2", "static", "/EXROLLBACK", "-") + +# RerunnableBatch 系は Orders → Orders2 の INSERT。実行前に Orders2 を空にする。 +$clearOrders2 = { Invoke-Sql "DELETE FROM [Orders2]" | Out-Null } +# 実行後は Orders と同数(830 件)になっていること。 +$verifyOrders2 = { + $src = [int](Invoke-Sql "SELECT COUNT(*) FROM [Orders]") + $dst = [int](Invoke-Sql "SELECT COUNT(*) FROM [Orders2]") + Write-Host (" Orders {0} 件 → Orders2 {1} 件" -f $src, $dst) + return ($dst -eq $src -and $src -gt 0) +} + +# ------------------------------------------------------------------ +# DaoGen_Tool(墨壺)の CUI モード +# ------------------------------------------------------------------ +# #508 で追加された CUI。2 モードを DAODEFGEN → DAOSQLGEN の順に実行し、 +# 前段が出力した定義 CSV を後段の入力に使う。 +# +# <パス区切りの注意> +# コマンドライン解析(StringVariableOperator.GetCommandArgs)は +# 「\」をエスケープ文字として扱うため、パスの区切りは「/」にする。 +# 「C:\temp\out」と書くと「\」が消えて別のパスになる(ツールの /HELP にも記載)。 +# +# <テンプレート> +# root/files/tools/DGenTemplates(DaoTemplate*.cs / *Template.xml などの平置き)。 + +$daoGenTemplate = ((Join-Path $csRoot "..\..\files\tools\DGenTemplates" | Resolve-Path).Path) -replace '\\', '/' + +# 対象を 2 テーブルに絞る。全テーブルを回すと時間がかかるだけで、 +# 疎通の確認としては同じことを見ている。 +$daoGenTables = "Shippers,Orders" + +# 作業フォルダを作る(net48 / Core で分ける) +function New-DaoGenWork([string]$tag) +{ + $work = Join-Path $OutputDir "daogen_$tag" + New-Item -ItemType Directory -Force (Join-Path $work "gen") | Out-Null + # 前回の生成物を残さない(残っていると「生成された」の判定が甘くなる) + Get-ChildItem $work -Recurse -File -EA SilentlyContinue | Remove-Item -Force -EA SilentlyContinue + return $work +} + +function New-DaoGenArgs([string]$tag, [string]$mode) +{ + $work = Join-Path $OutputDir "daogen_$tag" + $csv = ($work + "/DaoDef.csv").Replace("\", "/") + $gen = ($work + "/gen").Replace("\", "/") + + if ($mode -eq "DAODEFGEN") + { + return @("/CUI", "/MODE", "DAODEFGEN", "/OUTPUT", $csv, "/DAP", "SQL", "/TABLES", $daoGenTables) + } + return @("/CUI", "/MODE", "DAOSQLGEN", "/DAODEF", $csv, + "/TEMPLATE", $daoGenTemplate, "/OUTPUT", $gen, + "/DAP", "SQL", "/LANG", "CS", "/ENTITY") +} + +# 定義 CSV に対象テーブルが並んでいること +function Test-DaoDef([string]$tag) +{ + $csv = Join-Path (Join-Path $OutputDir "daogen_$tag") "DaoDef.csv" + if (-not (Test-Path $csv)) { Write-Host " 定義 CSV が生成されていない"; return $false } + + $text = Get-Content $csv -Raw + $ok = ($text -match 'Shippers') -and ($text -match 'Orders') + Write-Host (" 定義 CSV : {0} 行" -f (Get-Content $csv).Count) + return $ok +} + +# Dao・DTO・SQL が生成されていること +function Test-DaoGen([string]$tag) +{ + $gen = Join-Path (Join-Path $OutputDir "daogen_$tag") "gen" + $files = @(Get-ChildItem $gen -Recurse -File -EA SilentlyContinue) + Write-Host (" 生成ファイル : {0} 件" -f $files.Count) + + # Dao クラス(.cs)と 動的 SQL(.xml)と 静的 SQL(.sql)が揃っていること + $hasCs = @($files | Where-Object { $_.Name -eq "DaoShippers.cs" }).Count -gt 0 + $hasXml = @($files | Where-Object { $_.Extension -eq ".xml" }).Count -gt 0 + $hasSql = @($files | Where-Object { $_.Extension -eq ".sql" }).Count -gt 0 + return ($hasCs -and $hasXml -and $hasSql) +} + +$prepareDaoGen48 = { [void](New-DaoGenWork "net48") } +$prepareDaoGenCore = { [void](New-DaoGenWork "core") } +$daoDefArgs48 = New-DaoGenArgs "net48" "DAODEFGEN" +$daoSqlArgs48 = New-DaoGenArgs "net48" "DAOSQLGEN" +$daoDefArgsCore = New-DaoGenArgs "core" "DAODEFGEN" +$daoSqlArgsCore = New-DaoGenArgs "core" "DAOSQLGEN" +$verifyDaoDef48 = { Test-DaoDef "net48" } +$verifyDaoGen48 = { Test-DaoGen "net48" } +$verifyDaoDefCore = { Test-DaoDef "core" } +$verifyDaoGenCore = { Test-DaoGen "core" } + +# ------------------------------------------------------------------ +# HTTP 要求 +# ------------------------------------------------------------------ +# リダイレクトを追わずに状態コードを見たいが、Invoke-WebRequest は +# -MaximumRedirection 0 で 3xx を受け取ると、-SkipHttpErrorCheck を付けていても +# 「The maximum redirection count has been exceeded」で終了エラーになる。 +# ここで捕まえ、3xx を正常な結果として返す。 +# Cookie を引き継ぐため、セッションは呼び出し側で作って渡す。 +function New-WebSession +{ + return New-Object Microsoft.PowerShell.Commands.WebRequestSession +} + +function Invoke-Http +{ + param( + [string]$Uri, + [string]$Method = "GET", + $Body, + $Session + ) + + $p = @{ + Uri = $Uri; Method = $Method; WebSession = $Session + MaximumRedirection = 0 + # 5.1 は既定で Internet Explorer のエンジンを使い、未構成だと解析に失敗する。 + # 7 では受け付けられて無視されるため、常に付けてよい。 + UseBasicParsing = $true + } + # -SkipHttpErrorCheck は PowerShell 7 以降にしかない。 + # 5.1 に渡すとパラメータ束縛で失敗するので付けない。 + # (5.1 では 4xx/5xx が例外になるが、下の catch で状態コードを取り出す) + if ($PSVersionTable.PSVersion.Major -ge 6) { $p.SkipHttpErrorCheck = $true } + if ($Body) { $p.Body = $Body } + + try + { + $r = Invoke-WebRequest @p -ErrorAction Stop + return [pscustomobject]@{ Status = [int]$r.StatusCode; Content = $r.Content; Length = $r.RawContentLength } + } + catch + { + $resp = $_.Exception.Response + if ($resp) { return [pscustomobject]@{ Status = [int]$resp.StatusCode; Content = ""; Length = 0 } } + return [pscustomobject]@{ Status = -1; Content = $_.Exception.Message; Length = 0 } + } +} + +# ------------------------------------------------------------------ +# Web アプリの疎通手順 +# ------------------------------------------------------------------ +# 引数でベース URL を受け取り、@{ Ok = $bool; Detail = $string } を返す。 +# +# <確認の深さを揃える> +# 3 つとも「ログインを通して、認証が要る画面に到達できること」まで見る。 +# 入口ページが 200 を返すだけでは、ホスティングと構成しか確認できない。 +# 認証が要る画面まで通せば、ルーティング・認証・セッションまでを一度に確認できる。 +# +# | 対象 | 認証の実装 | 到達を確認する画面 | +# |----------------------|---------------------|----------------------| +# | MVC_Sample (net48) | FormsAuthentication | /Crud1/Index | +# | MVC_Sample (net10.0) | Cookie 認証 | /Crud1/Index | +# | WebForms_Sample | FormsAuthentication | Aspx/start/menu.aspx | +# +# いずれのサンプルも「ユーザー名が空でなければ認証する」実装のため、資格情報は不要。 + +# MVC_Sample : net48 は FormsAuthentication、net10.0 は Cookie 認証と実装は異なるが、 +# 画面構成と URL は同じなので同じ手順で確認できる。 +# 認証後の応答は net48 が 302(RedirectFromLoginPage)、net10.0 が 200(View を返す) +# と分かれるため、ここでは 4xx/5xx でないことだけを見る。 +$mvcLoginFlow = { + param($base) + + $ses = New-WebSession + + $r1 = Invoke-Http "$base/Home/Login" -Session $ses + if ($r1.Status -ne 200) { return @{ Ok = $false; Detail = "GET /Home/Login = $($r1.Status)" } } + + # ValidateAntiForgeryToken のため、画面からトークンを取り出して送り返す。 + $tok = ([regex]::Match($r1.Content, 'name="__RequestVerificationToken"[^>]*value="([^"]+)"')).Groups[1].Value + if (-not $tok) { return @{ Ok = $false; Detail = "__RequestVerificationToken が取得できない" } } + + # 500 はセッション状態サービスの停止など、環境側の問題であることが多い。 + $body = @{ UserName = "smoke"; Password = "smoke"; normal = "ログイン"; __RequestVerificationToken = $tok } + $r2 = Invoke-Http "$base/Home/Login" -Method POST -Body $body -Session $ses + if ($r2.Status -ge 400) { return @{ Ok = $false; Detail = "POST /Home/Login = $($r2.Status)" } } + + # 認証が要る画面。未認証ならログイン画面へ 302 されるため、200 なら認証が通っている。 + $r3 = Invoke-Http "$base/Crud1/Index" -Session $ses + if ($r3.Status -ne 200) { return @{ Ok = $false; Detail = "GET /Crud1/Index = $($r3.Status)(認証が通っていない)" } } + + return @{ Ok = $true; Detail = "ログイン後 /Crud1/Index = 200" } +} + +# WebForms_Sample (net48) : Web.config で <deny users="?" /> のため全画面が要認証。 +# ログイン後は defaultUrl の menu.aspx へ遷移する。 +$webFormsFlow = { + param($base) + + $ses = New-WebSession + + $r1 = Invoke-Http "$base/Aspx/start/login.aspx" -Session $ses + if ($r1.Status -ne 200) { return @{ Ok = $false; Detail = "GET login.aspx = $($r1.Status)" } } + + # WebForms のポストバックには、画面が発行した状態フィールドをそのまま返す必要がある。 + # __VIEWSTATE が取れること自体、ページのライフサイクルが動いている証拠でもある。 + $fields = @{} + foreach ($n in @("__VIEWSTATE", "__VIEWSTATEGENERATOR", "__EVENTVALIDATION")) + { + $m = [regex]::Match($r1.Content, ('name="' + $n + '"[^>]*value="([^"]*)"')) + if (-not $m.Success) { return @{ Ok = $false; Detail = "$n が取得できない" } } + $fields[$n] = $m.Groups[1].Value + } + + # マスタ ページ配下のため、コントロール名は ctl00$ContentPlaceHolder_A$ が付く。 + # btnButton1 がログイン ボタン(btnButton2 はキャンセル)。 + $fields["ctl00`$ContentPlaceHolder_A`$txtUserID"] = "smoke" + $fields["ctl00`$ContentPlaceHolder_A`$txtPassword"] = "smoke" + $fields["ctl00`$ContentPlaceHolder_A`$btnButton1"] = "ログイン" + + $r2 = Invoke-Http "$base/Aspx/start/login.aspx" -Method POST -Body $fields -Session $ses + if ($r2.Status -ge 400) { return @{ Ok = $false; Detail = "POST login.aspx = $($r2.Status)" } } + + # 認証が要る画面。未認証なら login.aspx へ 302 されるため、200 なら認証が通っている。 + $r3 = Invoke-Http "$base/Aspx/start/menu.aspx" -Session $ses + if ($r3.Status -ne 200) { return @{ Ok = $false; Detail = "GET menu.aspx = $($r3.Status)(認証が通っていない)" } } + + return @{ Ok = $true; Detail = "ログイン後 menu.aspx = 200" } +} + +$targets = @( + # --- バッチ (net48) --- + @{ + Name = "SimpleBatch_sample (net48)"; Bat = "5_Build_Bat_sample.bat" + Exe = "Samples\Bat_sample\SimpleBatch_sample\bin\Debug\SimpleBatch_sample.exe" + Args = $batchArgs; Expect = '\d+件のデータがあります' + } + @{ + Name = "RerunnableBatch_sample (net48)"; Bat = "5_Build_Bat_sample.bat" + Exe = "Samples\Bat_sample\RerunnableBatch_sample\bin\Debug\RerunnableBatch_sample.exe" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + @{ + Name = "RerunnableBatch_sample2 (net48)"; Bat = "5_Build_Bat_sample.bat" + Exe = "Samples\Bat_sample\RerunnableBatch_sample2\bin\Debug\RerunnableBatch_sample2.exe" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + @{ + Name = "RerunnableBatch_sample3 (net48)"; Bat = "5_Build_Bat_sample.bat" + Exe = "Samples\Bat_sample\RerunnableBatch_sample3\bin\Debug\RerunnableBatch_sample3.exe" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + + # --- バッチ (net10.0) --- + @{ + Name = "SimpleBatch_sample (net10.0)"; Bat = "5_Build_BatCore_sample.bat" + Exe = "Samples4NetCore\Legacy\Bat_sample\SimpleBatch_sample\bin\Debug\net10.0\SimpleBatch_sample.dll" + Args = $batchArgs; Expect = '\d+件のデータがあります' + } + @{ + Name = "RerunnableBatch_sample (net10.0)"; Bat = "5_Build_BatCore_sample.bat" + Exe = "Samples4NetCore\Legacy\Bat_sample\RerunnableBatch_sample\bin\Debug\net10.0\RerunnableBatch_sample.dll" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + @{ + Name = "RerunnableBatch_sample2 (net10.0)"; Bat = "5_Build_BatCore_sample.bat" + Exe = "Samples4NetCore\Legacy\Bat_sample\RerunnableBatch_sample2\bin\Debug\net10.0\RerunnableBatch_sample2.dll" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + @{ + Name = "RerunnableBatch_sample3 (net10.0)"; Bat = "5_Build_BatCore_sample.bat" + Exe = "Samples4NetCore\Legacy\Bat_sample\RerunnableBatch_sample3\bin\Debug\net10.0\RerunnableBatch_sample3.dll" + Args = $batchArgs; Pre = $clearOrders2; Verify = $verifyOrders2 + } + + # --- CLI (net10.0) --- + # net48 版は System.CommandLine / Sharprompt の .NET Fx サポート終了により + # ドロップされている(5_Build_CLI_sample.bat 参照)。 + # interactive サブコマンドは Prompt を使うため対象外とし、非対話のものを使う。 + @{ + Name = "Simple_CLI (net10.0)"; Bat = "5_Build_CLICore_sample.bat" + Exe = "Samples4NetCore\Legacy\CLI_sample\Simple_CLI\Simple_CLI\bin\Debug\net10.0\Simple_CLI.dll" + Args = @("cmd1", "--an-int", "123"); Expect = 'Sub command cmd1: 123' + } + + # --- DaoGen_Tool(墨壺)の CUI モード --- + # #508 で追加された /HELP と /CUI。GUI 側の確認は手作業に残る。 + # DAODEFGEN → DAOSQLGEN の順に実行し、前段の出力を後段の入力に使う。 + @{ + Name = "DaoGen_Tool /HELP (net48)"; Bat = "4_Build_Framework_Tool.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\OpenTouryo.DaoGen_Tool.exe" + Args = @("/HELP"); Expect = 'DaoGen_Tool(D層自動生成ツール/墨壺)' + } + @{ + Name = "DaoGen_Tool DAODEFGEN (net48)"; Bat = "4_Build_Framework_Tool.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\OpenTouryo.DaoGen_Tool.exe" + Args = $daoDefArgs48; Expect = '生成が完了しました。' + Pre = $prepareDaoGen48; Verify = $verifyDaoDef48 + } + @{ + Name = "DaoGen_Tool DAOSQLGEN (net48)"; Bat = "4_Build_Framework_Tool.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\OpenTouryo.DaoGen_Tool.exe" + Args = $daoSqlArgs48; Expect = '生成が完了しました。' + Verify = $verifyDaoGen48 + } + @{ + Name = "DaoGen_Tool /HELP (net10.0)"; Bat = "4_Build_Framework_ToolCore.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\net10.0-windows7.0\OpenTouryo.DaoGen_Tool.exe" + Args = @("/HELP"); Expect = 'DaoGen_Tool(D層自動生成ツール/墨壺)' + } + @{ + Name = "DaoGen_Tool DAODEFGEN (net10.0)"; Bat = "4_Build_Framework_ToolCore.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\net10.0-windows7.0\OpenTouryo.DaoGen_Tool.exe" + Args = $daoDefArgsCore; Expect = '生成が完了しました。' + Pre = $prepareDaoGenCore; Verify = $verifyDaoDefCore + } + @{ + Name = "DaoGen_Tool DAOSQLGEN (net10.0)"; Bat = "4_Build_Framework_ToolCore.bat" + Exe = "Frameworks\Tools\DaoGen_Tool\bin\Debug\net10.0-windows7.0\OpenTouryo.DaoGen_Tool.exe" + Args = $daoSqlArgsCore; Expect = '生成が完了しました。' + Verify = $verifyDaoGenCore + } + + # --- Web アプリ --- + @{ + Name = "MVC_Sample (net48)"; Bat = "10_Build_WebApp_sample.bat" + Kind = "Web"; WebHost = "IISExpress"; Port = 51081 + Site = "Samples\WebApp_sample\MVC_Sample\MVC_Sample" + Need = "aspnet_state" + Flow = $mvcLoginFlow + } + @{ + Name = "WebForms_Sample (net48)"; Bat = "10_Build_WebApp_sample.bat" + Kind = "Web"; WebHost = "IISExpress"; Port = 51082 + Site = "Samples\WebApp_sample\WebForms_Sample\WebForms_Sample" + Need = "aspnet_state" + Flow = $webFormsFlow + } + @{ + Name = "MVC_Sample (net10.0)"; Bat = "10_Build_WebAppCore_sample.bat" + Kind = "Web"; WebHost = "Kestrel"; Port = 51083 + Exe = "Samples4NetCore\Backend\MVC_Sample\MVC_Sample\bin\Debug\net10.0\MVC_Sample.dll" + Flow = $mvcLoginFlow + } +) + +# ------------------------------------------------------------------ +# ビルド +# ------------------------------------------------------------------ +function Invoke-BuildBat([string]$bat) +{ + $path = Join-Path $csRoot $bat + if (-not (Test-Path $path)) + { + Write-Host (" ビルド バッチが見つかりません : {0}" -f $bat) -ForegroundColor Red + return $false + } + + $log = Join-Path $OutputDir ("build_" + ($bat -replace '[^A-Za-z0-9]','_') + ".log") + + Push-Location $csRoot + # バッチ末尾(および途中)の pause に対応するため stdin を与える。 + cmd /c "echo. | call `"$path`"" *>&1 | Out-File $log -Encoding UTF8 + Pop-Location + + return $true +} + +# ------------------------------------------------------------------ +# Web ホストの起動・停止 +# ------------------------------------------------------------------ +# 起動しただけでは応答できないため、ポートが開くまで待ってから疎通する。 +function Wait-Port([int]$port, [int]$timeoutSec = 30) +{ + $sw = [Diagnostics.Stopwatch]::StartNew() + while ($sw.Elapsed.TotalSeconds -lt $timeoutSec) + { + $c = New-Object Net.Sockets.TcpClient + try + { + $c.Connect("127.0.0.1", $port) + if ($c.Connected) { $c.Close(); return $true } + } + catch { } + finally { $c.Dispose() } + Start-Sleep -Milliseconds 300 + } + return $false +} + +function Start-WebHost($t, [string]$log) +{ + if ($t.WebHost -eq "IISExpress") + { + $iis = Join-Path $env:ProgramFiles "IIS Express\iisexpress.exe" + if (-not (Test-Path $iis)) { return $null } + + $site = Join-Path $csRoot $t.Site + return Start-Process $iis ` + -ArgumentList "/path:`"$site`"", "/port:$($t.Port)", "/systray:false" ` + -PassThru -WindowStyle Hidden ` + -RedirectStandardOutput $log -RedirectStandardError "$log.err" + } + else + { + $dll = Join-Path $csRoot $t.Exe + if (-not (Test-Path $dll)) { return $null } + + # コンテンツ ルートを合わせるため、出力フォルダを作業ディレクトリにする。 + return Start-Process "dotnet" ` + -ArgumentList "`"$dll`"", "--urls", "http://localhost:$($t.Port)" ` + -PassThru -WindowStyle Hidden -WorkingDirectory (Split-Path $dll) ` + -RedirectStandardOutput $log -RedirectStandardError "$log.err" + } +} + +# ------------------------------------------------------------------ +# 実行 +# ------------------------------------------------------------------ +$selected = $targets | Where-Object { -not $Only -or $_.Name -like "*$Only*" } + +if (-not $SkipBuild) +{ + foreach ($bat in ($selected | ForEach-Object { $_.Bat } | Select-Object -Unique)) + { + Write-Host ("=== ビルド : {0} ===" -f $bat) -ForegroundColor Cyan + $sw = [Diagnostics.Stopwatch]::StartNew() + [void](Invoke-BuildBat $bat) + $sw.Stop() + Write-Host (" 完了 ({0:N1} 秒)" -f $sw.Elapsed.TotalSeconds) + } +} + +$results = @() + +foreach ($t in $selected) +{ + Write-Host "" + Write-Host ("=== {0} ===" -f $t.Name) -ForegroundColor Cyan + + $safe = ($t.Name -replace '[^A-Za-z0-9]', '_') + $out = Join-Path $OutputDir "$safe.txt" + + # ------------------------------------------------------------------ + # Web アプリ + # ------------------------------------------------------------------ + if ($t.Kind -eq "Web") + { + # 前提サービスの確認 + # ※ サービスの開始はシステムの状態を変えるため、ここでは行わない。 + # 足りない場合は対処方法を示して NG にする。 + if ($t.Need) + { + $svc = Get-Service $t.Need -EA SilentlyContinue + if (-not $svc -or $svc.Status -ne "Running") + { + $msg = "前提サービス {0} が動いていない → Start-Service {0}" -f $t.Need + Write-Host (" {0}" -f $msg) -ForegroundColor Yellow + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = "前提未達"; 内容 = $msg } + continue + } + } + + $sw = [Diagnostics.Stopwatch]::StartNew() + $proc = Start-WebHost $t $out + + if (-not $proc) + { + Write-Host " Web ホストを起動できません(実行ファイル/IIS Express が無い)" -ForegroundColor Red + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = "起動不可"; 内容 = "-" } + continue + } + + try + { + Write-Host (" 起動中 ... (PID {0}, port {1})" -f $proc.Id, $t.Port) + if (-not (Wait-Port $t.Port)) + { + Write-Host " ポートが開きません" -ForegroundColor Red + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = "NG"; 内容 = "ポートが開かない" } + continue + } + + $flow = & $t.Flow "http://localhost:$($t.Port)" + $sw.Stop() + + $verdict = if ($flow.Ok) { "OK" } else { "NG" } + Write-Host (" {0}" -f $flow.Detail) + Write-Host (" {0} ({1:N1} 秒)" -f $verdict, $sw.Elapsed.TotalSeconds) ` + -ForegroundColor $(if ($flow.Ok) { "Green" } else { "Red" }) + + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = $verdict; 内容 = $flow.Detail } + } + finally + { + # 子プロセスごと確実に落とす。 + Stop-Process -Id $proc.Id -Force -EA SilentlyContinue + } + continue + } + + # ------------------------------------------------------------------ + # プロセス(バッチ・CLI) + # ------------------------------------------------------------------ + $exe = Join-Path $csRoot $t.Exe + if (-not (Test-Path $exe)) + { + Write-Host " 実行ファイルが見つかりません" -ForegroundColor Red + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = "実行ファイル無し"; 内容 = "-" } + continue + } + + # 事前準備 + if ($t.Pre) + { + try { & $t.Pre } + catch + { + Write-Host (" 事前準備に失敗 : {0}" -f $_.Exception.Message) -ForegroundColor Red + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = "準備失敗"; 内容 = "-" } + continue + } + } + + # 実行 + Write-Host " 実行中 ..." + $sw = [Diagnostics.Stopwatch]::StartNew() + Push-Location (Split-Path $exe) + if ($exe -like "*.dll") + { + # 「/DAP」のように「/」で始まる引数は dotnet 自身のオプションと紛らわしいため、 + # 「--」で区切って渡す(リポジトリのビルド バッチも同じ渡し方をしている)。 + # 一方 System.CommandLine を使う CLI では「--」以降が未解析トークン扱いになり、 + # サブコマンドが認識されなくなるため、区切らずに渡す。 + $needSep = @($t.Args | Where-Object { $_ -like "/*" }).Count -gt 0 + if ($needSep) { & dotnet $exe -- @($t.Args) *>&1 | Out-File $out -Encoding UTF8 } + else { & dotnet $exe @($t.Args) *>&1 | Out-File $out -Encoding UTF8 } + } + else + { + & $exe @($t.Args) *>&1 | Out-File $out -Encoding UTF8 + } + Pop-Location + $sw.Stop() + + $text = Get-Content $out -Raw -EA SilentlyContinue + if ($null -eq $text) { $text = "" } + + # 判定 + # ※ 末尾の Console.ReadKey() 由来の例外はテスト内容と無関係なので除外する。 + $readKeyNoise = 'Cannot read keys when either application does not have a console' + $fatal = ($text -split "`r?`n") | Where-Object { + $_ -match 'Unhandled exception|ハンドルされない例外|System\.\w+Exception' -and + $_ -notmatch $readKeyNoise + } + + $ok = $true + $detail = "" + + if ($fatal) + { + $ok = $false + $detail = ($fatal | Select-Object -First 1).Trim() + Write-Host (" 例外 : {0}" -f $detail) -ForegroundColor Red + } + elseif ($t.Expect -and $text -notmatch $t.Expect) + { + $ok = $false + $detail = "期待する出力が無い : " + $t.Expect + Write-Host (" {0}" -f $detail) -ForegroundColor Red + } + + if ($ok -and $t.Expect) + { + $m = [regex]::Match($text, $t.Expect) + $detail = $m.Value + Write-Host (" 出力 : {0}" -f $m.Value) + } + + if ($ok -and $t.Verify) + { + if (-not (& $t.Verify)) + { + $ok = $false + $detail = "検証に失敗" + Write-Host " 検証に失敗" -ForegroundColor Red + } + } + + $verdict = if ($ok) { "OK" } else { "NG" } + Write-Host (" {0} ({1:N1} 秒)" -f $verdict, $sw.Elapsed.TotalSeconds) ` + -ForegroundColor $(if ($ok) { "Green" } else { "Red" }) + + $results += [pscustomobject]@{ 対象 = $t.Name; 結果 = $verdict; 内容 = $detail } +} + +# ------------------------------------------------------------------ +# サマリ +# ------------------------------------------------------------------ +Write-Host "" +Write-Host "================ サマリ ================" +$results | Format-Table -AutoSize -Wrap | Out-String | Write-Host +Write-Host (" ログ : {0}" -f $OutputDir) + +$ng = @($results | Where-Object { $_.結果 -ne "OK" }) +if ($ng.Count -eq 0) +{ + Write-Host " 全対象 OK" -ForegroundColor Green + exit 0 +} +else +{ + Write-Host (" {0} 件が NG" -f $ng.Count) -ForegroundColor Yellow + exit 1 +} diff --git a/root/programs/BUILDING.md b/root/programs/BUILDING.md new file mode 100644 index 000000000..98cd4e3f7 --- /dev/null +++ b/root/programs/BUILDING.md @@ -0,0 +1,223 @@ +# BUILDING.md — 全ビルドの実行と判定 + +対象: `root/programs/CS`(C# 側) +配置: `root/programs` +本書は、リリース時に行っていた「build バッチで全ビルドが通ることを確認」を、 +**合否が出る形に機械化**するための手順と判定基準を記述する(#513 段階 2)。 + +> **ビルド構成そのもの**(bat の一覧、ビルド順、`z_Common.bat` と `z_Common2.bat` の関係、 +> バージョン番号の一元管理、NuGet パッケージ化)は +> [`CS/Frameworks/ANALYSIS.md`](CS/Frameworks/ANALYSIS.md) の **7 章「ビルド」** が一次情報。 +> 本書はその上で「どう実行し、どう合否を判定するか」だけを扱う。 + +--- + +## 1. 使い方 + +```powershell +cd root\programs + +# 全ビルド(0_ExecAllBat.bat 相当)を実行し、合否を一覧表示する +.\1_BuildAll.ps1 + +# 一部のステップだけ実行する(動作確認用) +.\1_BuildAll.ps1 -Only "WebApp_sample" -SkipClean + +# ログの出力先を変える +.\1_BuildAll.ps1 -OutputDir D:\logs +``` + +終了コードは `0` = 全ステップ OK、`1` = NG あり。 + +| オプション | 内容 | +|---|---| +| `-Only <文字列>` | ステップ名/bat 名の部分一致で対象を絞る | +| `-SkipClean` | クリーン処理(`1_DeleteDir` / `1_DeleteFile`)を省略 | +| `-OutputDir <パス>` | ステップ別ログの保存先(既定 `%TEMP%\OpenTouryoBuildLogs`) | + +### `-SkipClean` の注意 + +**リリース判定では使わないこと。** 前回のビルド成果物が残っていると、 +実際にはビルドできない状態でも通ったように見える。 + +`1_DeleteDir.bat` は配下から `packages` `obj` `bin` `bld` `Temp` `PrecompiledWeb` +`MigrationBackup` `.vs` を再帰的に削除する。**Visual Studio は閉じてから実行する** +(`.vs` が削除されるため)。 + +--- + +## 2. なぜラッパーが必要か + +既存のビルド バッチをそのまま呼び出す構成にしてある。 +「何をビルドするか」の正はバッチ側に残り、`1_BuildAll.ps1` は実行と判定のみを担う。 + +ラッパーが必要な理由は次の 3 点。 + +1. **各バッチは MSBuild の終了コードを伝播しない**(`%ERRORLEVEL%` を見ていない) +2. **各バッチの末尾に `pause` がある**(対話入力を待つ) +3. **`-v:d`(詳細)で出力が膨大**(1 ステップで 6,000 行を超えることがある) + +このため、stdin を与えて実行し、出力から `error` / `warning` 行を抽出して判定している。 + +--- + +## 3. 判定基準 + +**エラー行が 1 件でもあれば NG**、無ければ OK。警告は件数を報告するだけで合否に影響しない。 + +エラー・警告の抽出は、次の形式の行を対象とする。 + +``` +xxx.csproj(12,5): error CS1002: ... ← コードあり +Microsoft.NuGet.targets(198,5): error : ... ← コードなし(NuGet の restore 失敗) +``` + +「ビルドに成功しました」等のサマリ文言は**ロケールで変わるため使わない**。 +`error` / `warning` とその後のコードは英語のまま出力されるため、そちらで判定する。 + +同一の指摘が複数プロジェクトから重複して出るため、一意化してから件数を数える。 + +### 警告について + +**警告 0 にはならない。** 現状の内訳は次のとおりで、いずれもコンパイル警告ではない。 + +| ステップ | 警告数 | 内容 | +|---|---|---| +| NuGet (netcore100) | 52 | `NU1903` 等、パッケージの脆弱性アドバイザリ | +| Business (netcore100) | 38 | 同上 | + +これらは依存パッケージ側の問題であり、ビルドの合否とは切り離している。 +**件数が大きく増減した場合は依存関係の変化を疑う**、という使い方をする。 + +--- + +## 4. 既知の環境依存 + +### WSClientWinCone_sample の署名エラー + +``` +error MSB3482: 署名中にエラーが発生しました: bin\Debug\app.publish\WSClientWinCone_sample.exe +の署名に失敗しました。SignTool Error: No certificates were found that met all the given criteria. +``` + +`WSClientWinCone_sample.csproj` は ClickOnce のマニフェスト署名が有効になっている。 + +```xml +<SignManifests>true</SignManifests> +<ManifestCertificateThumbprint>A69CDE3C92D8862D42E7A239134686E32089B679</ManifestCertificateThumbprint> +<ManifestKeyFile>WSClientWinCone_sample_TemporaryKey.pfx</ManifestKeyFile> +``` + +`.pfx` はリポジトリに同梱されているが、**MSBuild は拇印で証明書ストアを検索する**ため、 +当該証明書が入っていない環境ではビルドできない。 +`_TemporaryKey.pfx` の名のとおり Visual Studio が自動生成した開発用の一時証明書であり、 +同じ `WSClient_sample` 配下の `WSClientWin_sample` / `WSClientWPF_sample` に署名設定は無い。 + +**環境依存であり、コード側の不具合ではない。** ビルドを通すには、 +`.pfx` を証明書ストアにインポートするか、`SignManifests` を `false` にする +(`Install` は `false` のため配布用途でもない)。 + +--- + +## 5. 修正の経緯 : nuget.exe の MSBuild 誤検出 + +2026/08/01 時点で、net48 側の 7 ステップ・エラー 14 件が次の 2 種類で失敗していた。 + +``` +error MSB4226: インポートされたプロジェクト "...WebApplications\Microsoft.WebApplication.targets" + が見つかりませんでした。 +error : Your project file doesn't list 'win' as a "RuntimeIdentifier". +``` + +原因は、**`nuget.exe` が MSBuild を自動検出し、同居する SQL Server Management Studio の +MSBuild を選んでいた**こと。ログに次が出ていた。 + +``` +MSBuild 自動検出: 'C:\Program Files\Microsoft SQL Server Management Studio 22\Release\MSBuild\Current\bin' + から MSBuild バージョン '18.8.2.30814' を使用します。 +``` + +その MSBuild には Web アプリ用の `Microsoft.WebApplication.targets` が無く、 +また生成される `project.assets.json` が実際のビルド(Visual Studio の MSBuild)と噛み合わない。 + +`z_Common.bat` は `vswhere` で MSBuild を正しく解決していたが、 +**その値が `nuget.exe` に渡っていなかった**。このため次を追加した。 + +```bat +for %%i in (%BUILDFILEPATH%) do set MSBUILDDIR=%%~dpi +if defined MSBUILDDIR set MSBUILDDIR=%MSBUILDDIR:~0,-1% +set NUGET_MSBUILD=-MSBuildPath "%MSBUILDDIR%" +``` + +末尾の `\` を除去しているのは、`-MSBuildPath "...\"` だと `\"` がエスケープと解釈され、 +引数が壊れるため。この `%NUGET_MSBUILD%` を、`nuget.exe restore` を呼ぶ +**11 バッチ・20 箇所**に付与した。 + +結果、**7 ステップ NG → 1 ステップ NG**(残りは上記の署名エラーのみ)となった。 + +> MSBuild を同梱する製品(SSMS、Build Tools、旧 VS 等)が同居する環境では +> 同種の問題が起こり得る。`nuget.exe` 側にも MSBuild を明示する、という対処が要る。 + +--- + +## 6. 実行結果の例 + +``` +ステップ 結果 エラー 警告 秒 +-------- ---- ------ ---- -- +Clean (net48 基盤) OK 0 0 8.30 +NuGet (net48) OK 0 0 12.80 +Business (net48) OK 0 0 7.90 +... +NuGet (netcore100) OK 0 52 22.80 +Business (netcore100) OK 0 38 6.30 +... +WSClnt_sample (net48) NG 1 0 21.20 +... + + 所要時間 : 5.3 分 + 1 ステップが NG +``` + +全 31 ステップ(クリーン 8 + 実ビルド 23)で **約 5 分**。 + +--- + +## 7. 単体テストとの関係 + +ビルドが通ったら、単体テストの実行と判定を行う。 +手順は [`TESTING.md`](TESTING.md) を参照。 + +```powershell +.\2_RunAllTests.ps1 +``` + +**必ず `1_BuildAll.ps1` → `2_RunAllTests.ps1` の順で行う。** +`1_BuildAll.ps1` はクリーンを行い、`4_Build_CopyAssemblies.bat` が +テストの参照先(`Build_net48` / `Build_netcore100`)を更新するため、 +逆順ではテストが古いアセンブリを見ることになる。 + +なお `0_ExecAllBat.bat` は `y_Build_TestCode*.bat`(単体テスト)を含まない。 +テスト側のビルドは `2_RunAllTests.ps1` がバッチ経由で行うため、二重に実行する必要はない。 + +## 8. サンプルの疎通確認 + +単体テストが通ったら、サンプル アプリの疎通を確認する。 +手順は [`SMOKETEST.md`](SMOKETEST.md) を参照。 + +```powershell +.\3_SmokeTest.ps1 +``` + +**`1_BuildAll.ps1` はクリーンの繰り返しにより、完走後に net48 サンプルのバイナリを残さない。** +`1_DeleteDir.bat` が配下の `bin` / `obj` を再帰的に削除するため、最後にビルドされた +Core サンプルだけが残る。このため `3_SmokeTest.ps1` は対象を自分でビルドする。 + +### リリース時の実行順 + +```powershell +cd root\programs +.\1_BuildAll.ps1 # 全ビルドの合否 +.\2_RunAllTests.ps1 # 単体テストの回帰 +.\3_SmokeTest.ps1 # サンプルの疎通 +``` diff --git a/root/programs/CS/0_Release4Nuget.bat b/root/programs/CS/0_Release4Nuget.bat index a2e6fa2f1..2d104110c 100644 --- a/root/programs/CS/0_Release4Nuget.bat +++ b/root/programs/CS/0_Release4Nuget.bat @@ -8,7 +8,7 @@ echo | call 2_Build_NuGet_net48.bat timeout 5 echo | call 1_DeleteDir.bat -echo | call 2_Build_NuGet_nettcore80.bat +echo | call 2_Build_NuGet_netcore100.bat @echo on timeout 5 diff --git a/root/programs/CS/10_Build_WebAppCore_sample.bat b/root/programs/CS/10_Build_WebAppCore_sample.bat index 56e4393c1..20eb10f27 100644 --- a/root/programs/CS/10_Build_WebAppCore_sample.bat +++ b/root/programs/CS/10_Build_WebAppCore_sample.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -19,12 +19,8 @@ rem -------------------------------------------------- rem Batch build of MVC_Sample. rem -------------------------------------------------- -set CURRENTDIR=%cd% -cd "Samples4NetCore\Backend\MVC_Sample\MVC_Sample" -if exist "node_modules" rd /s /q "node_modules" -call RestoreLib1.bat -call RestoreLib2.bat -cd %CURRENTDIR% +@rem npm / grunt によるクライアント ライブラリの復元は廃止した。 +@rem (wwwroot\lib 配下をリポジトリに直接格納する方式に移行済み) dotnet restore "Samples4NetCore\Backend\MVC_Sample\MVC_Sample.sln" dotnet msbuild %COMMANDLINE% "Samples4NetCore\Backend\MVC_Sample\MVC_Sample.sln" diff --git a/root/programs/CS/10_Build_WebApp_sample.bat b/root/programs/CS/10_Build_WebApp_sample.bat index fbd9753a8..5770bb537 100644 --- a/root/programs/CS/10_Build_WebApp_sample.bat +++ b/root/programs/CS/10_Build_WebApp_sample.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of WebForms_Sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\WebApp_sample\WebForms_Sample\WebForms_Sample.sln" +..\nuget.exe restore "Samples\WebApp_sample\WebForms_Sample\WebForms_Sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WebApp_sample\WebForms_Sample\WebForms_Sample.sln" pause @@ -26,7 +26,7 @@ pause rem -------------------------------------------------- rem Batch build of MVC_Sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\WebApp_sample\MVC_Sample\MVC_Sample.sln" +..\nuget.exe restore "Samples\WebApp_sample\MVC_Sample\MVC_Sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WebApp_sample\MVC_Sample\MVC_Sample.sln" pause diff --git a/root/programs/CS/1_DeleteDir.bat b/root/programs/CS/1_DeleteDir.bat index 05ed92469..99f1dc138 100644 --- a/root/programs/CS/1_DeleteDir.bat +++ b/root/programs/CS/1_DeleteDir.bat @@ -1,4 +1,4 @@ -@echo off +@echo off set DIRECTORIES=packages, obj, bin, bld, Temp, PrecompiledWeb, MigrationBackup, .vs @echo -------------------------------------------------- diff --git a/root/programs/CS/2_Build_NuGet_net48.bat b/root/programs/CS/2_Build_NuGet_net48.bat index 5d6e15523..783f351e2 100644 --- a/root/programs/CS/2_Build_NuGet_net48.bat +++ b/root/programs/CS/2_Build_NuGet_net48.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,10 +18,10 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Build the batch Infrastructure(Nuget48) rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Infrastructure\Nuget_net48.sln" +..\nuget.exe restore "Frameworks\Infrastructure\Nuget_net48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Infrastructure\Nuget_net48.sln" -..\nuget.exe restore "Frameworks\Infrastructure\Nuget_RichClient_net48.sln" +..\nuget.exe restore "Frameworks\Infrastructure\Nuget_RichClient_net48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Infrastructure\Nuget_RichClient_net48.sln" pause diff --git a/root/programs/CS/3_Build_Business_net48.bat b/root/programs/CS/3_Build_Business_net48.bat index 39ccf9e81..a0f86bfda 100644 --- a/root/programs/CS/3_Build_Business_net48.bat +++ b/root/programs/CS/3_Build_Business_net48.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -19,7 +19,7 @@ rem -------------------------------------------------- rem Build the Infrastructures rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Infrastructure\Business_net48.sln" +..\nuget.exe restore "Frameworks\Infrastructure\Business_net48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Infrastructure\Business_net48.sln" pause diff --git a/root/programs/CS/4_Build_Framework_Tool.bat b/root/programs/CS/4_Build_Framework_Tool.bat index fcce053e2..15d1763b1 100644 --- a/root/programs/CS/4_Build_Framework_Tool.bat +++ b/root/programs/CS/4_Build_Framework_Tool.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of DPQuery_Tool. rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Tools\DPQuery_Tool\DPQuery_Tool.sln" +..\nuget.exe restore "Frameworks\Tools\DPQuery_Tool\DPQuery_Tool.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tools\DPQuery_Tool\DPQuery_Tool.sln" pause @@ -26,7 +26,7 @@ pause rem -------------------------------------------------- rem Batch build of DaoGen_Tool. rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Tools\DaoGen_Tool\DaoGen_Tool.sln" +..\nuget.exe restore "Frameworks\Tools\DaoGen_Tool\DaoGen_Tool.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tools\DaoGen_Tool\DaoGen_Tool.sln" pause diff --git a/root/programs/CS/5_Build_2CS_sample.bat b/root/programs/CS/5_Build_2CS_sample.bat index a6ca71725..38b66e6a9 100644 --- a/root/programs/CS/5_Build_2CS_sample.bat +++ b/root/programs/CS/5_Build_2CS_sample.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of 2CSClientWin_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\2CS_sample\2CSClientWin_sample\2CSClientWin_sample.sln" +..\nuget.exe restore "Samples\2CS_sample\2CSClientWin_sample\2CSClientWin_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\2CS_sample\2CSClientWin_sample\2CSClientWin_sample.sln" pause @@ -26,7 +26,7 @@ pause rem -------------------------------------------------- rem Batch build of GenDaoAndBatUpd_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\2CS_sample\GenDaoAndBatUpd_sample\GenDaoAndBatUpd_sample.sln" +..\nuget.exe restore "Samples\2CS_sample\GenDaoAndBatUpd_sample\GenDaoAndBatUpd_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\2CS_sample\GenDaoAndBatUpd_sample\GenDaoAndBatUpd_sample.sln" pause @@ -34,7 +34,7 @@ pause rem -------------------------------------------------- rem Batch build of TimeStamp_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\2CS_sample\TimeStamp_sample\TimeStamp_sample.sln" +..\nuget.exe restore "Samples\2CS_sample\TimeStamp_sample\TimeStamp_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\2CS_sample\TimeStamp_sample\TimeStamp_sample.sln" pause @@ -42,7 +42,7 @@ pause rem -------------------------------------------------- rem Batch build of 2CSClientWPF_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\\2CS_sample\2CSClientWPF_sample\2CSClientWPF_sample.sln" +..\nuget.exe restore "Samples\\2CS_sample\2CSClientWPF_sample\2CSClientWPF_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\\2CS_sample\2CSClientWPF_sample\2CSClientWPF_sample.sln" pause diff --git a/root/programs/CS/5_Build_Bat_sample.bat b/root/programs/CS/5_Build_Bat_sample.bat index 11f4c5d0e..1627c678d 100644 --- a/root/programs/CS/5_Build_Bat_sample.bat +++ b/root/programs/CS/5_Build_Bat_sample.bat @@ -18,6 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of SimpleBatch_sample. rem -------------------------------------------------- +..\nuget.exe restore "Samples\Bat_sample\SimpleBatch_sample\SimpleBatch_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\Bat_sample\SimpleBatch_sample\SimpleBatch_sample.sln" pause @@ -25,6 +26,7 @@ pause rem -------------------------------------------------- rem Batch build of RerunnableBatch_sample. rem -------------------------------------------------- +..\nuget.exe restore "Samples\Bat_sample\RerunnableBatch_sample\RerunnableBatch_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\Bat_sample\RerunnableBatch_sample\RerunnableBatch_sample.sln" pause @@ -32,6 +34,7 @@ pause rem -------------------------------------------------- rem Batch build of RerunnableBatch_sample2. rem -------------------------------------------------- +..\nuget.exe restore "Samples\Bat_sample\RerunnableBatch_sample2\RerunnableBatch_sample2.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\Bat_sample\RerunnableBatch_sample2\RerunnableBatch_sample2.sln" pause @@ -39,6 +42,7 @@ pause rem -------------------------------------------------- rem Batch build of RerunnableBatch_sample3. rem -------------------------------------------------- +..\nuget.exe restore "Samples\Bat_sample\RerunnableBatch_sample3\RerunnableBatch_sample3.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\Bat_sample\RerunnableBatch_sample3\RerunnableBatch_sample3.sln" pause diff --git a/root/programs/CS/5_Build_CLI_sample.bat b/root/programs/CS/5_Build_CLI_sample.bat index f32353d67..84a94647a 100644 --- a/root/programs/CS/5_Build_CLI_sample.bat +++ b/root/programs/CS/5_Build_CLI_sample.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. diff --git a/root/programs/CS/6_Build_WSSrv_sample.bat b/root/programs/CS/6_Build_WSSrv_sample.bat index 2d5ae92d7..8c9f18697 100644 --- a/root/programs/CS/6_Build_WSSrv_sample.bat +++ b/root/programs/CS/6_Build_WSSrv_sample.bat @@ -24,6 +24,7 @@ md "Samples\WS_sample\Build" rem -------------------------------------------------- rem Batch build of WSServer_sample. rem -------------------------------------------------- +..\nuget.exe restore "Samples\WS_sample\WSServer_sample\WSServer_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WS_sample\WSServer_sample\WSServer_sample.sln" xcopy /E /Y "Samples\WS_sample\WSServer_sample\bin\%BUILD_CONFIG%" "Samples\WS_sample\Temp\%BUILD_CONFIG%\" diff --git a/root/programs/CS/7_Build_Framework_WS.bat b/root/programs/CS/7_Build_Framework_WS.bat index f6964b626..2965cce5c 100644 --- a/root/programs/CS/7_Build_Framework_WS.bat +++ b/root/programs/CS/7_Build_Framework_WS.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of ServiceInterface(ASPNETWebService). rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Infrastructure\ServiceInterface\ASPNETWebService\ASPNETWebService.sln" +..\nuget.exe restore "Frameworks\Infrastructure\ServiceInterface\ASPNETWebService\ASPNETWebService.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Infrastructure\ServiceInterface\ASPNETWebService\ASPNETWebService.sln" pause @@ -34,7 +34,7 @@ pause rem -------------------------------------------------- rem Batch build of ServiceInterface(WCFService). rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Infrastructure\ServiceInterface\WCFService\WCFService.sln" +..\nuget.exe restore "Frameworks\Infrastructure\ServiceInterface\WCFService\WCFService.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Infrastructure\ServiceInterface\WCFService\WCFService.sln" pause diff --git a/root/programs/CS/7_Build_Framework_WSCore.bat b/root/programs/CS/7_Build_Framework_WSCore.bat index 11e2561a9..292d576a8 100644 --- a/root/programs/CS/7_Build_Framework_WSCore.bat +++ b/root/programs/CS/7_Build_Framework_WSCore.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. diff --git a/root/programs/CS/8_Build_WSClnt_sample.bat b/root/programs/CS/8_Build_WSClnt_sample.bat index b67fefb9a..08c51dadd 100644 --- a/root/programs/CS/8_Build_WSClnt_sample.bat +++ b/root/programs/CS/8_Build_WSClnt_sample.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of WSClientWin_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWin_sample\WSClientWin_sample.sln" +..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWin_sample\WSClientWin_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WS_sample\WSClient_sample\WSClientWin_sample\WSClientWin_sample.sln" pause @@ -26,7 +26,7 @@ pause rem -------------------------------------------------- rem Batch build of WSClientWPF_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWPF_sample\WSClientWPF_sample.sln" +..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWPF_sample\WSClientWPF_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WS_sample\WSClient_sample\WSClientWPF_sample\WSClientWPF_sample.sln" pause @@ -41,7 +41,7 @@ pause rem -------------------------------------------------- rem Batch build of WSClientWinCone_sample. rem -------------------------------------------------- -..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSClientWinCone_sample.sln" +..\nuget.exe restore "Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSClientWinCone_sample.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Samples\WS_sample\WSClient_sample\WSClientWinCone_sample\WSClientWinCone_sample.sln" pause diff --git a/root/programs/CS/99_BuildLibsAtOtherRepos.bat b/root/programs/CS/99_BuildLibsAtOtherRepos.bat index e7524a966..e42530f1d 100644 --- a/root/programs/CS/99_BuildLibsAtOtherRepos.bat +++ b/root/programs/CS/99_BuildLibsAtOtherRepos.bat @@ -1,5 +1,14 @@ @echo off +@rem ************************************************** +@rem [注意] このバッチは現在動作しません(未保守)。 +@rem 呼び出している net45 / net46 / net47 / netstd20 / +@rem netcore20 / netcore30 用のバッチは既に存在しません。 +@rem xcopy 元の Build_net45 ... Build_netcore30 も生成されません。 +@rem 現行の targetFramework は net48 / netcore100 です。 +@rem 使用する場合は全面的な見直しが必要です。 +@rem ************************************************** + @rem 本バッチファイルの作成にあたり、以下のサイトを参考にしました。 @rem 【Bat】【vim】香り屋Vimをダウンロードしてインストールまでするbatファイル - Qiita @rem https://qiita.com/koryuohproject/items/beed1a28ad6a1f60256d diff --git a/root/programs/CS/99_BuildLibsAtOtherReposInTimeOfDev.bat b/root/programs/CS/99_BuildLibsAtOtherReposInTimeOfDev.bat index b6e7feda0..8de9dcef1 100644 --- a/root/programs/CS/99_BuildLibsAtOtherReposInTimeOfDev.bat +++ b/root/programs/CS/99_BuildLibsAtOtherReposInTimeOfDev.bat @@ -1,5 +1,14 @@ @echo off +@rem ************************************************** +@rem [注意] このバッチは現在動作しません(未保守)。 +@rem 呼び出している net45 / net46 / net47 / netstd20 / +@rem netcore20 / netcore30 用のバッチは既に存在しません。 +@rem xcopy 元の Build_net45 ... Build_netcore30 も生成されません。 +@rem 現行の targetFramework は net48 / netcore100 です。 +@rem 使用する場合は全面的な見直しが必要です。 +@rem ************************************************** + @rem 本バッチファイルの作成にあたり、以下のサイトを参考にしました。 @rem 【Bat】【vim】香り屋Vimをダウンロードしてインストールまでするbatファイル - Qiita @rem https://qiita.com/koryuohproject/items/beed1a28ad6a1f60256d diff --git a/root/programs/CS/Frameworks/ANALYSIS.md b/root/programs/CS/Frameworks/ANALYSIS.md new file mode 100644 index 000000000..6f7608022 --- /dev/null +++ b/root/programs/CS/Frameworks/ANALYSIS.md @@ -0,0 +1,644 @@ +# ANALYSIS.md — Open棟梁 フレームワーク本体(CS/Frameworks)コード分析 + +対象: `root/programs/CS/Frameworks` / ブランチ: `develop` +最終更新: 2026-07-31 + +本書は **コーディング・エージェントが本リポジトリで作業する際の Context** を目的とした分析結果である。 +「どこに何があるか」「どの規約に従うべきか」「何を壊しやすいか」を記す。 + +--- + +## 1. これは何か + +`Open棟梁 (OpenTouryo)` は、日立ソリューションズ発の .NET 用アプリケーション・フレームワーク(Apache-2.0)。 +2007年から継続開発されており、**P層(画面)/B層(業務ロジック)/D層(データアクセス)の3層モデル**と、 +**「UOC」= User Own Coding(利用者が実装する拡張ポイント)** という設計思想が全体を貫く。 + +- 上流ドキュメント: `OpenTouryoDocuments` リポジトリ(本リポジトリ外) +- 配布形態: NuGet パッケージ(`Touryo.Infrastructure.*` / アセンブリ名 `OpenTouryo.*`) +- プロジェクト・ポリシーは **リポジトリ ルートの `AGENTS.md`(`CLAUDE.md` はそれへのポインタ)** に定義済み。 + → **エージェントは git 操作(add/commit/push/checkout/branch/reset/restore/stash)を行わない。** + 作業結果はワーキング ツリーに残し、変更内容を報告するに留める。 + +--- + +## 2. ディレクトリとアセンブリの対応 + +### 2.1 `Infrastructure/`(フレームワーク本体) + +| ディレクトリ | アセンブリ | ルート名前空間 | 役割 | +|---|---|---|---| +| `Public/` | `OpenTouryo.Public` | `Touryo.Infrastructure.Public` | 汎用ライブラリ。フレームワーク非依存で単体利用可 | +| `Public/Security/` | `OpenTouryo.Public.Security` | `...Public.Security` | 暗号・署名・JWT/JWS/JWE・鍵交換・パスワードハッシュ | +| `Public/Db/Dam*/` | `OpenTouryo.Dam*` | `...Public.Db` | DBMS 別データアクセス制御(Dam)の別アセンブリ | +| `Framework/` | `OpenTouryo.Framework` | `...Framework` | フレームワーク中核(P/B/D の親クラス、通信、認証、例外) | +| `Framework/RichClient/` | `OpenTouryo.Framework.RichClient` | `...Framework.RichClient` | WinForms/WPF 向け | +| `Business/` | `OpenTouryo.Business` | `...Business` | **業務フレームワーク=テンプレート層**。アプリ側でカスタマイズ前提 | +| `Business/RichClient/` | `OpenTouryo.Business.RichClient` | `...Business.RichClient` | 同上(リッチクライアント) | +| `CustomControl/` | `OpenTouryo.CustomControl` | `...CustomControl` | ASP.NET Web Forms カスタム コントロール(net48 のみ) | +| `CustomControl/RichClient/` | `OpenTouryo.CustomControl.RichClient` | `...CustomControl.RichClient` | WinForms カスタム コントロール | +| `ServiceInterface/` | — | — | サービス公開ホスト(ASP.NET WebAPI / WCF-TCP)。net48 のみ | + +ファイル数の目安: Public 188 / Framework 76 / CustomControl 50 / Business 42 / ServiceInterface 10。 + +### 2.2 `Tools/` — 開発支援 GUI ツール(WinForms) + +- `DaoGen_Tool` : DB スキーマから D層 Dao クラス+SQL(XML) を自動生成 +- `DPQuery_Tool` : DPQ(動的パラメタライズド・クエリ)XML の編集・検証 + +### 2.3 `Tests/` — テスト(**xUnit/NUnit ではない**) + +| 名前 | 内容 | +|---|---| +| `TestCode` | コンソール EXE。`Program.cs` から `Test*.Root()` を順次呼ぶ手動確認型。期待値は `Result48.txt` / `ResultCore100.txt` と目視比較 | +| `TestLog` | ログ出力確認(log4net/NLog、1〜3) | +| `TestBatch` | バッチ起動確認 | +| `EncAndDecUtil` / `EncAndDecUtilCUI` | 暗号・署名ユーティリティの GUI/CUI 確認 | + +**重要:** テスト プロジェクトはフレームワークを `ProjectReference` ではなく +**`HintPath` で `Infrastructure/Build_netcore100/net10.0/*.dll` を参照**する。 +→ **フレームワークを先にビルドしないとテストは古い DLL を見る。** +また `net48` / `core100` の 2 プロジェクトが `..\*.cs` を `Link` で共有する(実体は 1 つ)。 + +--- + +## 3. アーキテクチャ:呼び出しフロー + +``` +[P層] 画面コード + BaseController(Web Forms) / BaseMVController(MVC5) / BaseMVControllerCore(ASP.NET Core MVC) + ↓ MyBase*Controller(Business層のテンプレート)を継承してアプリが実装 + ↓ +[通信] CallController.Invoke(serviceName, parameterValue) + ↓ ProtocolNameService でプロトコル解決(TMProtocolDefinition.xml) + ↓ InProcessNameService で assembly/class 解決(TMInProcessDefinition.xml) + ↓ Latebind.InvokeMethod → "DoBusinessLogic" + ↓ +[B層] BaseLogic.DoBusinessLogic(parameterValue, iso) + ├ UOC_ConnectionOpen … Dam 生成/Connection Open/BeginTransaction + ├ UOC_PreAction … ACCESS ログ等 + ├ UOC_DoAction … ★業務処理。MyFcBaseLogic は "UOC_" + MethodName へ Latebind 振り分け + ├ UOC_AfterAction + ├ Commit(_dam と _dams[key] すべて) + ├ UOC_AfterTransaction + └ catch → Rollback → UOC_ABEND(例外種別ごとに 3 オーバーロード) + finally → ConnectionClose + ↓ +[D層] BaseDao ← MyBaseDao ← CmnDao / アプリ個別 Dao + ↓ +[DAM] BaseDam ← DamSqlSvr / DamODBC / DamOLEDB / DamMySQL / DamPstGrS / DamManagedOdp / DamDB2 / DamHiRDB +``` + +### 3.1 引数・戻り値クラス + +`BaseParameterValue`(`ScreenId` / `ControlId` / `MethodName` / `ActionType`、すべて読み取り専用) +→ `MyParameterValue`(+ `MyUserInfo User`)→ `_3TierParameterValue`(検索条件・ソート・ページング等) + +`BaseReturnValue`(`ErrorFlag` / `ErrorMessageID` / `ErrorMessage` / `ErrorInfo`) +→ `MyReturnValue` → `_3TierReturnValue` + +- `[Serializable]`。WS 越えのため。 +- `ActionType` は `"SQL%common"` のように **`%` 区切りの複合文字列**。 + 先頭要素が **データ プロバイダ選択キー**(`SQL`/`OLE`/`ODB`/`ODP`/`MCN`/`NPS`/`DB2`/`HIR`)として + `MyBaseLogic.UOC_ConnectionOpen` / `MyFcBaseLogic.UOC_ConnectionOpen` で分岐する。 + +### 3.2 自動振り分け(重要なマジック) + +`MyFcBaseLogic.UOC_DoAction` は `"UOC_" + parameterValue.MethodName` を **リフレクションで呼ぶ**。 +戻り値は `ref` では戻らない(例外時に失われる)ため、**`this.ReturnValue` プロパティ経由で受け渡す**。 + +```csharp +private void UOC_SelectCount(TestParameterValue p) // private でよい +{ + TestReturnValue r = new TestReturnValue(); + this.ReturnValue = r; // ★必ず冒頭で設定する + ... +} +``` + +`ReturnValue` の setter は `WasCalledFromDoBusinessLogic` フラグを見ており、 +`DoBusinessLogic` 経由でない呼び出しでは `FrameworkException` を投げる。 + +### 3.3 例外モデル + +| 例外 | 意味 | `DoBusinessLogic` の挙動 | +|---|---|---| +| `BusinessApplicationException` | 業務例外(想定内) | Rollback → `ErrorFlag=true` を戻り値に設定 → **リスローしない** | +| `BusinessSystemException` | 業務システム例外 | Rollback → `UOC_ABEND` → **リスロー** | +| `Exception`(その他) | 想定外 | Rollback → `UOC_ABEND(ref)` → **リスローしない**(UOC 側で必要なら throw) | +| `FrameworkException` | フレームワーク内部エラー | 上位へ | + +すべて `messageID` プロパティを持つ(`Information` は `BusinessApplicationException` のみ)。 + +--- + +## 4. データアクセス(Open棟梁の中核的な差別化要素) + +### 4.1 3 つのクエリ形態(`DbEnum.QueryStatusEnum`) + +- **SPQ** 静的パラメタライズド・クエリ … `.sql` ファイル +- **DPQ** 動的パラメタライズド・クエリ … `.xml` ファイル。`<WHERE>` / `<IF>` / `<ELSE>` で + **パラメタが設定されている条件行だけを動的に組み立てる**(SQL インジェクション耐性を保ったまま動的 WHERE を実現) + +```xml +<ROOT> + SELECT [ShipperID],[CompanyName] FROM [Shippers] + <WHERE> + WHERE + <IF>AND [ShipperID] = @ShipperID<ELSE>AND [ShipperID] IS NULL</ELSE></IF> + <IF>AND [CompanyName] LIKE @CompanyName_Like</IF> + </WHERE> +</ROOT> +``` + +サンプルは `root/files/resource/Sql/`(`sqlserver` / `oracle` / `mysql` / `pstgrs` / `db2` / `hirdb` / `ole_odbc` 別サブディレクトリあり)。 + +### 4.2 Dam / Dao の責務 + +- `BaseDam`(3198 行、`Public/Db/BaseDam.cs`)… SQL ロード、パラメタ記号変換(`@`/`:`/`?`)、DPQ 展開、 + トランザクション制御、コマンド タイムアウトを担う。DBMS 差異はここに集約。 +- `BaseDao` … `SetSqlByFile` / `SetSqlByCommand` / `SetParameter` / `ExecSelectFill_DT` / + `ExecSelect_DR` / `ExecSelectScalar` / `ExecInsUpDel_NonQuery` を `protected` で提供。 + UOC は `UOC_PreQuery` / `UOC_AfterQuery(sql)` / `UOC_AfterQuery(sql, ex)`。 +- `MyBaseDao` … `SetSqlByFile2`(`appSettings:sqlTextFilePath` を基点にパス解決。 + `MyBaseDao.UseEmbeddedResource = true` で埋め込みリソースへ切替)+ SQLTRACE ログ・性能測定。 +- `CmnDao` … Dao クラスを書かずに使える汎用 Dao。パラメタを `Dictionary` に溜め、実行直前に反映。 + `BaseDao` のメソッドを `new` で隠蔽して `public` 化している(**`override` ではない点に注意**)。 +- `_3TierEngine`(1452 行)… `_3TierParameterValue` の検索条件辞書から SQL を生成する CRUD エンジン。 + `DaoGen_Tool` が生成するコードとセットで使う。 + +### 4.3 分離レベル + +`DbEnum.IsolationLevelEnum`: `NotConnect`(接続しない) / `NoTransaction` / `ReadUncommitted` / +`ReadCommitted` / `RepeatableRead` / `Serializable` / `Snapshot` / `DefaultTransaction` / `User`。 +`User` は「B層テンプレート側で決める」の意で、`MyBaseLogic` では `ReadCommitted` にフォールバックする。 + +--- + +## 5. 設定(XML 定義ファイル + appSettings) + +### 5.1 XML 定義ファイル(`root/files/resource/Xml/`) + +| appSettings キー | ファイル | 用途 | +|---|---|---| +| `FxXMLMSGDefinition` | `MSGDefinition[_ja/_zh-CN].xml` | メッセージ ID → 文言(`GetMessage`) | +| `FxXMLSPDefinition` | `SPDefinition.xml` | 共有プロパティ(`GetSharedProperty`) | +| `FxXMLSCDefinition` | `SCDefinition.xml` | 画面遷移定義(`BaseController` の遷移チェック) | +| `FxXMLTCDefinition` | `TCDefinition.xml` | トランザクション定義(`TransactionControl`)。接続文字列キー+分離レベル(`nc/nt/uc/rc/rr/sz/ss/df`) | +| `FxXMLTMInProcessDefinition` | `TMInProcessDefinition.xml` | インプロセス名前解決(論理名→assembly/class) | +| `FxXMLTMProtocolDefinition` | `TMProtocolDefinition.xml` | プロトコル/URL/タイムアウト/プロパティ | + +読み込み順は **埋め込みリソース → 物理ファイル → 未設定なら空 XML(OFF 扱い)→ それ以外はエラー**。 +パスには `%ENV%` 形式の環境変数を展開できる(`StringVariableOperator.BuiltStringIntoEnvironmentVariable`)。 + +### 5.2 主な appSettings キー(`Fx` プレフィクス) + +- 画面制御: `FxSessionTimeOutCheck` `FxDoubleTransmissionCheck` `FxScreenTransitionMode` + `FxScreenTransitionCheck` `FxErrorScreenPath` `FxOKMessageDialogPath` `FxYesNoMessageDialogPath` + `FxDialogFramePath` `Fx*IconPath` `Fx*MaxQueueLength` `FxDefault*Style` `FxCacheControl` +- コントロール接頭辞(集約イベント ハンドラの識別に使う): `FxPrefixOfButton` `FxPrefixOfTextBox` … 等 15 種 +- DB: `FxSqlCacheSwitch` `FxSqlCommandTimeout` `FxSqlDotnetTypeInfo` `FxSqlEncoding` `FxSqlTraceLog` +- ログ: `FxLog4NetConfFile` / `LogLib`(`"nlog"` で NLog、既定は log4net) +- 国際化: `FxExceptionMessageCulture` `FxBusinessMessageCulture` +- 実行環境: `FxContainerization`(**true のとき環境変数を appSettings より優先**。JSON キーの `:` は `__` で表現) +- `_3TierEngine` 用: `MethodNameHeaderS/FooterS` `MethodNameHeaderD/FooterD` + `MethodLabel_Ins/Sel/Upd/Del/SelCnt` `UpdateParamHeader/Footer` `LikeParamHeader/Footer` +- Dao: `sqlTextFilePath` / 接続文字列 `ConnectionString_SQL|OLE|ODBC|ODP|MCN|NPS|DB2|HIR` + +### 5.3 設定の読み取り API + +`Public/Util/GetConfigParameter.cs` に集約。 +- net48: `System.Configuration`(`app.config` / `web.config`) +- .NET (Core): `Microsoft.Extensions.Configuration`。**使用前に `GetConfigParameter.InitConfiguration(...)` が必須** + (`IConfiguration` / `IConfigurationBuilder` / JSON ファイル名 / 引数なし=`appsettings.json` の 4 オーバーロード)。 + JSON は `"appSettings": { ... }` セクション配下に置く慣習。 + +--- + +## 6. マルチ ターゲットと条件コンパイル(**最も事故りやすい箇所**) + +### 6.1 ターゲット + +| 系統 | csproj 命名 | TFM | +|---|---|---| +| .NET Framework | `*_net48.csproj` / `*_net48.sln` | `v4.8`(旧形式 csproj) | +| .NET | `*_netcore100.csproj` / `*_netcore100.sln` | `net10.0`(SDK 形式) | +| リッチクライアント (.NET) | 同上 | `net10.0-windows7.0` | + +出力先は `Infrastructure/Build_net48/` と `Infrastructure/Build_netcore100/net10.0/`(`.gitignore` 対象)。 + +### 6.2 プリプロセッサ シンボル + +| シンボル | 定義のされ方 | 意味 | +|---|---|---| +| `NETCOREAPP` | **.NET SDK が net10.0 に暗黙定義**(csproj の記述に依存しない) | 「.NET (Core) ビルド」=実質「非 net48」 | +| `NETSTD` | `Framework` / `Public.Security` / `Dam*` の `DefineConstants` に**明示** | 歴史的経緯(下記) | +| `NET48` | net48 側 | .NET Framework 固有 | +| `NETCOREAPP2_0` | 旧コード内に残存 | 実質デッド分岐 | +| `PERFORMANCE_LOG_SWITCH` | 任意 | 性能ログ | + +#### なぜ 2 つあるのか(歴史的経緯) + +かつては **.NET Standard でビルドされるライブラリ**と **.NET Core でビルドされるライブラリ**が +併存しており、その区別が `NETSTD` / `NETCOREAPP` だった。 +**現在は .NET Standard 版が全て .NET Core(net10.0)に統一された**ため、この区別は意味を失っている。 + +#### 現在の実際の成立状況(実測) + +**`NETCOREAPP` は .NET SDK が net10.0 ターゲットに自動的に定義する暗黙シンボル**であり、 +`<DefineConstants>` に書かれていなくても **全 netcore100 プロジェクトで真**になる +(同条件の最小プロジェクトを作って `#warning` で確認済み)。 + +| プロジェクト | `NETCOREAPP` | `NETSTD` | +|---|---|---| +| `Public` / `Business` / `Business.RichClient` / `CustomControl.RichClient` / `Framework.RichClient` | ✓(暗黙) | **✗** | +| `Framework` / `Public.Security` / `Dam*` | ✓(暗黙) | ✓(明示) | +| net48 の全プロジェクト | ✗ | ✗ | + +したがって現状は次が成り立つ。 + +- `#if NETCOREAPP` … netcore100 ビルドで**常に真**。 +- `#if (NETSTD || NETCOREAPP)` … `#if NETCOREAPP` と**完全に等価**。 +- `#if NETSTD` … `NETSTD` を明示定義した 3 系統でのみ真。**それ以外では偽になる。** + +#### 注意点 + +**`NETSTD` を明示していないプロジェクト(`Public` / `Business` / `*.RichClient`)の中で +素の `#if NETSTD` を書くと、黙って net48 側の分岐に落ちる。** +実測では該当箇所は 0 件(下表のとおり、書き分けは現状すべて正しい)だが、コード追加時の落とし穴になる。 + +| プロジェクト | `(NETSTD \|\| NETCOREAPP)` | `NETSTD` 単独 | `NETCOREAPP` 単独 | +|---|---:|---:|---:| +| `Public` | 36 | 0 | 2 | +| `Public.Security` | 0 | 83 | 0 | +| `Framework` | 21 | 8 | 1 | +| `Framework.RichClient` | 0 | 0 | 1 | +| `Business` | 0 | 0 | 6 | +| `Business.RichClient` | 0 | 0 | 4 | +| `CustomControl.RichClient` | 0 | 0 | 27 | + +> **整理の余地**: 上記のとおり 3 つの書き方はすべて `NETCOREAPP`(=非 net48)と等価に帰着する。 +> `<DefineConstants>` から `NETSTD` を削除し、`#if NETSTD` / `#if (NETSTD || NETCOREAPP)` を +> `#if NETCOREAPP` に統一すれば、このシンボル体系は 1 本化できる(対象 約 150 箇所)。 +> 機械的だが影響範囲が広いため、実施は別途判断。 + +### 6.3 csproj の `Compile Remove` によるファイル除外 + +SDK 形式 csproj はワイルドカード込みなので、**プラットフォーム非対応ファイルを `Compile Remove` で明示的に外している**。 +新規ファイルを追加すると **net10.0 側に自動で含まれてしまう**ため、Windows 専用 API を使う場合は +`Compile Remove` の追加が必要。主な除外例: + +- `Public_netcore100`: `Win32/**` `WinProc/**` `Security/**` `Db/Dam*/**`、 + `IO/BinarySerialize.cs` `IO/Zip*.cs` `Log/CustomEventLog.cs` `Log/SecurityEventLog.cs` + `Db/DamOLEDB.cs` `Db/DamOraClient.cs` `Util/SharedMemory.cs` +- `Framework_netcore100`: `RichClient/**`、`Presentation/BaseController.cs`(Web Forms) + `Presentation/BaseMasterController.cs` `Presentation/BaseMVController.cs` `Presentation/FxEventArgs.cs` + `Transmission/IWCFTCPSvcForFx.cs` `Util/FxSessionUtil.cs` `Util/FxHttpQueryStringIndex.cs` +- `Business_netcore100`: `Csp/**` `RichClient/**`、 + **`Business/MyBaseLogic.cs` と `Business/_3TierEngine.cs` / `Common/_3Tier*Value.cs`**、 + `Presentation/MyBaseController.cs` `MyBaseMVController.cs` `MyBaseAsyncApiController.cs` 他 +- `Public.Security_netcore100`: `IdentityImpersonation.cs` `KeyExg/EcdhCng*.cs` + +→ **`_3TierEngine` と `MyBaseLogic` は net48 専用**。.NET (Core) 側で使うのは `MyFcBaseLogic` 系。 + +### 6.4 net48 専用の機能 + +- ASP.NET Web Forms 一式(`BaseController` 4836 行、`CustomControl/`) +- `CallController` のリモート プロトコル(`FxEnum.TmProtocol` は .NET (Core) では `InProcess` のみ): + ASP.NET WS / WCF-HTTP / WCF-TCP / ASP.NET WebAPI(JSON-RPC) +- `ServiceInterface/`(WCF ホスト、ASP.NET WebAPI ホスト) + +--- + +## 7. ビルド + +`root/programs/CS/` 直下の連番 `.bat` をダブルクリック実行する運用(`_Please run with a double-click...txt`)。 + +| bat | 内容 | +|---|---| +| `2_Build_NuGet_net48.bat` / `2_Build_NuGet_netcore100.bat` | `Nuget_*.sln` + `Nuget_RichClient_*.sln` をビルド(=フレームワーク本体) | +| `3_Build_Business_*.bat` / `3_Build_BusinessRichClient_*.bat` | Business 層 | +| `4_Build_CopyAssemblies.bat` / `4_Build_Framework_Tool*.bat` | 成果物コピー・ツール | +| `5〜8_*` | サンプル各種 | +| `y_Build_TestCode*.bat` | テスト | +| `0_ExecAllBat.bat` | 全実行 | +| `z_Common.bat` / `z_Common2.bat` | ビルド ツールのパス解決(各 bat が冒頭で `call` する) | + +.NET (Core) 側は `dotnet restore` → `dotnet msbuild` を呼ぶだけなので、 +**エージェントは bat を経由せず直接 `dotnet build "Frameworks\Infrastructure\Nuget_netcore100.sln"` してよい。** +net48 側は MSBuild / devenv が必要(Windows + VS 前提)。 + +`dotnet build Nuget_netcore100.sln` は **0 エラー / 20 警告**。 +警告はすべて NuGet 脆弱性警告(12 節)で、コンパイル警告ではない。 + +#### `z_Common.bat` と `z_Common2.bat`(MSBuild 版 / devenv 版) + +両者は **`%BUILDFILEPATH%`(ビルド ツールのパス)と `%COMMANDLINE%`(ビルド引数)という +同じインターフェイスを提供する差し替え可能な対**であり、呼び出し側の bat は +`call` するファイルを変えるだけでビルド ツールを切り替えられる設計になっている。 + +| | ビルド ツール | `%COMMANDLINE%` | +|---|---|---| +| `z_Common.bat` | MSBuild.exe | `/p:Configuration=<構成> /p:DebugType=<型> -v:d` | +| `z_Common2.bat` | devenv.com / devenv.exe | `/build <構成>`(devenv 構文) | + +`z_Common2.bat` は、**MSBuild.exe ではエラーになるが devenv.com では通る、というケースが +散在していた時期に、ビルド ツールを devenv へ差し替えるために用意されたもの**。 +現在はどの bat からも呼ばれておらず、変数定義にも不具合が残っているため、そのままでは動作しない +(詳細はファイル冒頭のコメント参照)。**通常は `z_Common.bat` を使う。** + +`z_Common.bat` は `vswhere` で MSBuild を解決し、見つからなければ明示エラーで停止する +(固定パス群はフォールバックとして存置)。エディションに依存しない。 + +### 7.1 ビルド順(厳守) + +``` +Public → Public.Security → Framework → Business → Tools / Tests / Samples +``` + +**`4_Build_CopyAssemblies.bat`(`Build_net48` → `Build\` の xcopy)を飛ばすと、 +net48 のサンプルとツールが一切ビルドできない。** +`Frameworks\Infrastructure\Build\` を `HintPath` 参照するプロジェクトが CS/VB 合わせて **42 件**あるため +(`Samples/*` の全 net48 サンプル、`Tools/DaoGen_Tool`・`DPQuery_Tool`、`Tests/TestLog*`)。 +`0_ExecAllBat.bat` が `2_`/`3_` → `4_CopyAssemblies` → `5_`〜`10_`(サンプル)の順で呼ぶのはこのため。 + +`Build\` に入るのは **net48 の成果物のみ**で、.NET (Core) 側に相当物は無い +(`Samples4NetCore` は `Build_netcore100\net10.0\` を直接参照する)。この非対称は設計どおり。 + +### 7.2 バージョン番号の一元管理 + +**`Infrastructure/Directory.Build.props` の `OpenTouryoVersion` が唯一の定義箇所。** + +```xml +<PropertyGroup> + <OpenTouryoVersion>3.0.0</OpenTouryoVersion> + <Company>Hitachi Solutions</Company> +</PropertyGroup> +``` + +| 反映先 | 仕組み | +|---|---| +| SDK 形式アセンブリ(7 個) | 各 csproj の `<Version>$(OpenTouryoVersion)</Version>` | +| NuGet パッケージ | nuspec は `<version>$version$</version>` と `<dependency id="Touryo.Infrastructure.*" version="$version$" />`。`_NuGetPack.bat` が props から値を読み `nuget pack -Properties version=...` で渡す | + +- **旧形式 csproj(`*_net48.csproj`)には効かない。** `Microsoft.Common.props` をインポートしないため。 + net48 のバージョンは各プロジェクトの `Properties\AssemblyInfo.cs` が持つ。 +- **`Business` 系は 1.0.0 で別系統。** `Business/Properties/AssemblyInfo.cs` が `AssemblyVersion("1.0.0.0")` であり、 + Public / Framework / Public.Security の 3.0.0.0 とは意図的に分けている。 + そのため `Directory.Build.props` では `<Version>` を全体に設定せず、 + `OpenTouryoVersion` という独自プロパティをパッケージ対象の 7 プロジェクトだけが参照する形にしている。 + +> **注意**: `Directory.Build.props` の XML コメント内にハイフン 2 個の連続(`--`)を書くと +> XML として不正になり、MSBuild がプロジェクトの読み込みに失敗する。区切り線に使わないこと。 + +### 7.3 NuGet パッケージ化 + +`root/programs/CS/NuGet/`(`*.nuspec` + `_NuGetPack.bat`、`in/` に DLL を staging)。 +手順は `NuGet/_手順の説明.txt` を参照。 + +- **nuspec の `<dependencies>` は csproj の `PackageReference` と一致している**(余分・不足・版ズレなし)。 + 依存を増減したら nuspec 側も合わせること。 +- パッケージ自身と `Touryo.Infrastructure.*` の相互依存のバージョンは `$version$` トークンで自動追随する(7.2 節)。 +- `Symbol_Framework.RichClient.nuspec` のみ、`net10.0-windows7.0` ビルドを `lib\net10.0` に配置している(12 節)。 + +--- + +## 8. コーディング規約(既存コードに合わせること) + +### 8.1 ファイル ヘッダ(**新規追加時も必須**。ただし新規と既存で書式が異なる) + +#### 新規ファイルに付けるヘッダ(これが現行の書式) + +```csharp +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// ...(定型 15 行) +// +#endregion + +//********************************************************************************** +//* クラス名 :CallController +//* クラス日本語名 :クライアント ライブラリ +//* +//* 作成者 :xxx +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2026/07/31 xxx 新規作成 +//********************************************************************************** +``` + +※ 更新者は ClaudeCode:玄人 幸道、GitHubCopilot:後輩 郎党 で。 + +> **`Copyright (C) ... Hitachi Solutions,Ltd.` のブロックは、新規ファイルには付けない。** +> 開発元が企業からコミュニティに移ったため。 +> Apache License の region と、クラス名・日本語名・更新履歴のブロックは従来どおり必要。 + +#### 既存ファイルの場合 + +既存ファイルの先頭には次の Copyright ブロックが付いている。**これは削除せず、そのまま残す。** + +```csharp +//********************************************************************************** +//* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. +//********************************************************************************** +``` + +**既存ファイルを変更した場合は、更新履歴に 1 行追記するのがこのリポジトリの慣習。** + +### 8.2 その他の規約 + +- **コメント・XML ドキュメントは日本語**。`<summary>` は全 public/protected メンバに付与 + (`DocumentationFile` を出力しているため、欠けると警告)。 +- `#region` / `#endregion` による細かいブロック分割が徹底されている(`BaseController` は 100 以上)。 +- `<remarks>自由に利用できる。</remarks>` … 業務コードから直接呼んでよい API の目印。 + `<remarks>業務コード親クラス1から利用される派生の末端</remarks>` … オーバーライド専用の目印。 +- 拡張ポイントは **`UOC_` プレフィクス**(`FxLiteral.UOC_METHOD_HEADER`)。 + P層の集約イベント ハンドラも `UOC_<ControlId>_Click` のような命名規則でリフレクション解決される。 +- 定数は `FxLiteral`(Framework, 777 行)/ `MyLiteral`(Business)/ `PubLiteral`(Public)に集約。 + **文字列リテラル直書きではなく、これらに定数を追加する。** +- 命名: `Base*`(Framework 提供の抽象)→ `My*`(Business 層テンプレート、アプリで改変前提)。 + アプリ側は `LayerB` / `LayerD` / `TestParameterValue` / `TestReturnValue` を実装(`Samples/` 参照)。 +- 変数はプライベート フィールド `_xxx` + 明示的プロパティ(自動プロパティは新しい箇所のみ)。 + +### 8.3 bat ファイルの文字コード + +**非 ASCII 文字(日本語)を含む `.bat` は UTF-8 BOM 付きにする。** + +BOM が無いと、cmd.exe がバッチをバイト オフセットで読み進める際に文字境界がずれ、 +**`@rem` コメントの途中から先がコマンドとして実行される**ことがある +(`'xxx' は、内部コマンドまたは外部コマンド…として認識されていません` が出る)。 + +| BOM | 起動 CP=932 | 起動 CP=65001 | +|---|---|---| +| なし | エラーなし | **エラーあり(間欠)** | +| **あり** | **エラーなし** | **エラーなし** | + +- 実害は「紛らわしいエラー表示」に留まり、**後続の実コマンドは飛ばない**。 +- `chcp 65001` は**画面出力の文字化け対策**であって、この解析ずれの対策ではない。 + 日本語を `echo` する場合に併用する。 +- 純粋に ASCII のみの bat に BOM は不要(差分ノイズになるだけ)。 + **日本語を書き足すときに BOM の有無を確認すること。** + +`root/programs/CS/` 配下で非 ASCII を含む bat は、すべて BOM 付きになっている。 + +### 8.4 ps1 ファイルの文字コードと、PowerShell 5.1 / 7 の両対応 + +**`.ps1` は Windows PowerShell 5.1 と PowerShell 7 の両方で動くこと。** + +開発時は `pwsh`(7)で確認しがちだが、利用者は `powershell.exe`(5.1)で実行する。 +7 だけで確認すると 5.1 で落ちる。既踏の落とし穴は次の 4 点。 + +| 事象 | 原因 | 対処 | +|---|---|---| +| 構文エラー・文字化け(`繧ケ繝・ャ繝・`) | 5.1 は BOM 無しの `.ps1` を **ANSI(Shift_JIS)**として読む | **UTF-8 BOM 付き**で保存する | +| 同じファイルなのに差分が出る | `Get-Content` の既定エンコードが 5.1 は ANSI、7 は UTF-8 | **`-Encoding UTF8`** を明示する | +| HTTP が常に失敗(状態コード `-1`) | `-SkipHttpErrorCheck` は **7 以降にしかない** | バージョンを見て付け外しする | +| 実行中に画面がクリアされ、それまでの結果が消える | 子プロセスの `chcp 65001` はコンソール全体に影響する | スクリプト冒頭で先に切り替える | + +```powershell +# 7 専用の引数は、バージョンを見て付け外しする +if ($PSVersionTable.PSVersion.Major -ge 6) { $p.SkipHttpErrorCheck = $true } + +# コンソールのコード ページと、PowerShell の出力エンコードは別物。判定を分けること +if ((cmd /c chcp) -notmatch '65001') { cmd /c chcp 65001 | Out-Null } +if ([Console]::OutputEncoding.CodePage -ne 65001) +{ + [Console]::OutputEncoding = New-Object Text.UTF8Encoding $false +} +``` + +- **`.bat` は「非 ASCII を含むときだけ」BOM 付き**(8.3)だが、 + **`.ps1` は非 ASCII を含むなら必ず BOM 付き**。5.1 が既定で ANSI として読むため。 +- 5.1 の `[Console]::OutputEncoding` は**起動時の値のまま**で、実行中にコード ページが + 変わっても追随しない。同じ画面で 2 回目を実行したときに化ける原因になる。 +- **変更したら 5.1 でも実行して確かめること。** + +```powershell +powershell.exe -NoProfile -Command "Set-Location 'root\programs'; .\3_SmokeTest.ps1" +``` + +検証スクリプト側での具体的な適用例は +[`SMOKETEST.md`](../../SMOKETEST.md) 「PowerShell 5.1 と 7 の両対応」を参照。 + +--- + +## 9. Public 層の主なユーティリティ(再実装しないこと) + +| 名前空間 | 主なクラス | +|---|---| +| `Public.Db` | `BaseDam` `SQLUtility` `DbEnum` `Dam*` | +| `Public.Dto` | `DTTable/DTRow/DTColumn`(マーシャリング可能な自前 DataTable)、`DataToPoco` `PocoToPoco` `DataToDictionary` | +| `Public.Str` | `CustomEncode`(Base64/Hex/URL) `StringChecker` `FormatChecker` `StringConverter` `FormatConverter` `CheckCharCode` `JIS2k4Checker` | +| `Public.Security` | `SymmetricCryptography` `ASymmetricCryptography` `GetHash` `GetKeyedHash` `MsgAuthCode` `DigitalSign*` `PrivacyEnhancedMail`、`Jwt/`(JWS RS/ES/HS 256-512、JWE RSA1_5+A128CBC-HS256 / RSA-OAEP+AES-GCM、`JwkSet`、鍵コンバータ)、`Aead/`、`KeyExg/`(ECDH/RSA)、`Pwd/GetPasswordHashV1/V2` | +| `Public.Log` | `LogIF`(静的 façade)。ロガー名は慣習的に `"ACCESS"` と `"SQLTRACE"`。バックエンドは `LogLib` 設定で log4net / NLog | +| `Public.Reflection` | `Latebind`(フレームワークの動的呼び出しの心臓部)、`MyAssemblies` | +| `Public.FastReflection` | `AccessorCacher` `CompiledExpressionCreater` `InstanceCreator<T>` `EnumToString*Extensions` | +| `Public.IO` | `ResourceLoader` `EmbeddedResourceLoader` `DeflateCompression` `ExponentialBackoff` `Zipper/UnZipper`(net48) | +| `Public.Util` | `GetConfigParameter` `PerformanceRecorder` `RandomValueGenerator` `EnvInfo` `PubCmnFunction` | +| `Public.Diagnostics` | `MyDebug`(`OutputDebugAndConsole`)`ObjectInspector` `StackFrameOperator` | +| `Public.Win32` / `WinProc` | P/Invoke 群(net48 のみ) | + +--- + +## 10. 認証まわり(`Framework/Authentication/`) + +比較的新しく、直近も更新されている領域(`fixed #503` / `#504` は `SAML2Client.cs`)。 + +- `OAuth2AndOIDCClient` … Authorization Code / PKCE(S256) / Client Credentials / ROPC / + Refresh / UserInfo / Revoke / Introspect / JWT Bearer / Device AuthZ / CIBA / Request Object / JWK Set。 + **すべて `static async Task<string>`(生 JSON を返す)**。`HttpClient` は `static` プロパティで差し替え可能。 +- `OAuth2AndOIDCConst` / `OAuth2AndOIDCEnum` / `OAuth2AndOIDCParams` / `CmnClientParams` +- トークン型: `CmnJwtToken` `AccessToken` `IdToken` `JwtAssertion` `RequestObject` `ResponseObject` `ClaimsInRO` +- `JwkSetStore` … JWK Set のキャッシュ +- SAML2: `SAML2Client`(`CreateRedirectRequest` / `CreatePostRequest` / `VerifyResponse`)、 + `SAML2Bindings` `SAML2Const` `SAML2Enum` `SAML2Params` +- 依存: `jose-jwt` 5.1.1 / `BouncyCastle.NetCore` 2.2.1(`Public.Security`) + +--- + +## 11. 主要な依存パッケージ(netcore100) + +| プロジェクト | パッケージ | +|---|---| +| Public | `log4net` 3.3.0, `NLog` 5.5.0, `Microsoft.Data.SqlClient` 6.0.1, `System.Data.Odbc` 9.0.4, `Newtonsoft.Json` 13.0.3, `Microsoft.Extensions.Configuration*` 9.0.4, `Zipangu` 1.1.8 | +| Public.Security | `jose-jwt` 5.1.1, `BouncyCastle.NetCore` 2.2.1, `System.Security.Cryptography.Xml` 9.0.15, `Newtonsoft.Json` 13.0.3 | +| Framework | `Microsoft.AspNetCore.{Http,Http.Extensions,Mvc,Session}` 2.3.0, `Microsoft.Extensions.PlatformAbstractions` 1.1.0 | +| Business | `Microsoft.AspNetCore.Authentication{,.Cookies}` 2.3.0, `Microsoft.AspNetCore.{Http,Mvc}` 2.3.0, `System.Security.Cryptography.Xml` 9.0.4, `Newtonsoft.Json` 13.0.3 ほか | + +**注意 1:** `Microsoft.AspNetCore.*` は **2.3.0(互換シム パッケージ)** を使い続けている。 +net10.0 のフレームワーク参照(`Microsoft.AspNetCore.App`)ではない。安易に上げると壊れる可能性が高い。 + +**注意 2:** `System.Security.Cryptography.Xml` は **`Public.Security` が 9.0.15、`Business` が 9.0.4** と +版がずれている(Dependabot が `Public.Security` のみ更新したため)。どちらも NU1903 が出る(12 節)。 + +依存は Dependabot で随時更新される。**上表は目安であり、正確な値は csproj を直接見ること。** + +--- + +## 12. 落とし穴 / 既知の不整合(作業前に把握しておく) + +1. **`4_Build_CopyAssemblies.bat` を飛ばすと net48 のサンプル・ツールが全滅する**(7.1 節)。 +2. **`Compile Remove` を忘れると .NET (Core) ビルドが壊れる**(6.3 節)。 +3. **`CmnDao` は `new` による隠蔽**であって override ではない。`BaseDao` 型変数経由で呼ぶと親の実装が走る。 +4. **`ReturnValue` を設定し忘れると戻り値が null** になる(3.2 節)。例外時も同様。 +5. **`_dams` ディクショナリと `_dam` の二重管理**。Commit/Rollback/Close は両方に対して行われる。 + 複数 DB を使う場合は `SetDam(key, dam)` を使い、`GetDam(key)` で取り出す。 +6. **`BaseController.cs`(4836 行)と `BaseDam.cs`(3198 行)は巨大**。 + 変更時は該当 `#region` に閉じた修正に留め、全体リファクタは避ける(互換性維持が最優先の設計)。 +7. **VB 版ミラーが存在**: `root/programs/VB/Frameworks/Infrastructure/` に + `Business` / `CustomControl` / `ServiceInterface` の VB.NET 版がある(`Public` / `Framework` は C# 版を共有)。 + Business 層テンプレートの仕様を変えると **VB 側も追随が必要**。 +8. **作業ツリーに未追跡の生成物が残る**。`Build*/` と `ServiceInterface/*/dll/` は `.gitignore` 済み。 + 残るのは `*.cer`(テスト生成物)と `SAML2Client.cs.bak`(残骸)で、いずれもコミット対象ではない。 +9. `Public/Security/MyDebug.cs` は `Public/Diagnostics/MyDebug.cs` の**派生クラス**(重複ではない。 + アセンブリ分割の都合)。 +10. `TMProtocolDefinition2.xml` など「2」付きの定義ファイルが並存する。用途は用例違い。 +11. **`System.Security.Cryptography.Xml` に既知脆弱性(NU1903 / 高)**。 + - `Public.Security` = 9.0.15 → `Nuget_netcore100.sln` のビルドで **20 警告** + - `Business` = 9.0.4 → `Business_netcore100.sln` のビルドで **18 警告** + - 修正版の有無を確認したうえで更新するか、`NoWarn` での抑止を検討する。 + 版を上げる場合は net48 / netcore100 の両 csproj と `NuGet/*.nuspec` の `<dependencies>` を同時に直す。 +12. **`Symbol_Framework.RichClient.nuspec` の lib TFM が不正確**。 + `net10.0-windows7.0` ビルドを `lib\net10.0` に配置している。本来は `lib\net10.0-windows` が正しく、 + 現状は Linux 上の net10.0 消費者も解決してしまう。直すとパッケージ解決セマンティクスが変わるため据え置き。 + +--- + +## 13. サンプル(フレームワークの正しい使い方の参照先) + +> **詳細な分析は各ディレクトリの ANALYSIS.md を参照:** +> - `../Samples/ANALYSIS.md`(net48 版サンプル) +> - `../Samples4NetCore/ANALYSIS.md`(.NET 10 版サンプル) + +| パス | 内容 | +|---|---| +| `Samples/WebApp_sample/` | ASP.NET Web Forms / MVC5(net48) | +| `Samples/2CS_sample/` | 2層 C/S(WinForms / WPF) | +| `Samples/Bat_sample/` | バッチ(`SimpleBatch` / `RerunnableBatch` 1〜3) | +| `Samples/CLI_sample/` `Samples/WS_sample/` | CLI / Web サービス | +| `Samples4NetCore/Backend/MVC_Sample` `ASPNETWebService` | .NET (Core) 版 | +| `Samples4NetCore/Legacy/` | 上記の .NET (Core) 移植版 | + +典型的な B層実装は `Samples/Bat_sample/SimpleBatch_sample/Business/LayerB.cs`(`MyFcBaseLogic` 継承)。 +「テンプレ」`#region` に `UOC_メソッド名` という雛形がそのまま残っているのが本フレームワークの流儀。 + +--- + +## 14. エージェント向け作業チェックリスト + +- [ ] `AGENTS.md` のポリシー遵守(**git 操作をしない**) +- [ ] 変更対象が net48 / netcore100 / 両方のどれか判定(`Compile Remove` を確認) +- [ ] 条件コンパイルは **`#if NETCOREAPP`(=非 net48)を使う**。 + `#if NETSTD` は `Framework` / `Public.Security` / `Dam*` でしか真にならないので新規には使わない(6.2 節) +- [ ] 新規 .cs にはヘッダ コメント(Apache License / クラス名・日本語名・更新履歴)を付与。 + **Copyright ブロックは新規には付けない**(8.1 節) +- [ ] 既存 .cs 変更時は更新履歴に 1 行追記 +- [ ] public/protected メンバに日本語 `<summary>` を付与(DocumentationFile 出力のため) +- [ ] 文字列リテラルは `FxLiteral` / `MyLiteral` / `PubLiteral` に定数として追加 +- [ ] ビルド確認: `dotnet build Frameworks/Infrastructure/Nuget_netcore100.sln` + (net48 は MSBuild 必須) +- [ ] テスト実行前に **フレームワークを先にビルド**(`Build_netcore100/net10.0/*.dll` を HintPath 参照するため) +- [ ] Business 層テンプレートを変えたら VB 版ミラーの追随要否を報告 diff --git a/root/programs/CS/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs b/root/programs/CS/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs index a35534586..4927409fb 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Business/Presentation/MyBaseMVControllerCore.cs @@ -31,11 +31,14 @@ //* 2018/07/19 西野 大介 復元後のユーザー情報をSessionに設定するコードを追加 //* 2018/08/08 西野 大介 MyMVCCoreFilterAttributeをFilterAttributeとして設定 //* 2021/05/23 西野 大介 キャッシュ制御ヘッダの二重追加エラーの対応 +//* 2026/07/31 玄人 幸道 net48版から移植漏れのアクセスログ出力点を追加 +//* (View、OnResultExecuting、OnResultExecuted) //********************************************************************************** using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; @@ -74,15 +77,45 @@ namespace Touryo.Infrastructure.Business.Presentation { /// <summary>画面コード親クラス2</summary> /// <remarks>(オーバーライドして)自由に利用できる。</remarks> + /// <remarks> + /// IResultFilter を実装しているのは、ASP.NET Core の Controller が + /// IActionFilter / IAsyncActionFilter しか実装しておらず、 + /// OnResultExecuting / OnResultExecuted を override できないため。 + /// コントローラが IResultFilter を実装していると、MVC が ControllerResultFilter を + /// 自動的にフィルタ パイプラインへ追加し、本クラスの実装を呼び出す。 + /// (フィルタ属性ではなくコントローラ側に実装するのは、属性インスタンスが + ///  リクエスト間で共有され、性能測定用の状態を持たせられないため。) + /// </remarks> [MyMVCCoreFilter()] - public class MyBaseMVControllerCore : BaseMVControllerCore + public class MyBaseMVControllerCore : BaseMVControllerCore, IResultFilter { - /// <summary>性能測定</summary> + /// <summary>性能測定(アクション実行区間)</summary> private PerformanceRecorder perfRec; + /// <summary>性能測定(結果実行=レンダリング区間)</summary> + /// <remarks> + /// アクション実行区間の perfRec とは別インスタンスにする。 + /// .NET (Core) 版の PerformanceRecorder は Stopwatch ベースで、 + /// EndsPerformanceRecord の後に再度 Ends を呼んでも値が変わらないため、 + /// perfRec を使い回すとレンダリング区間が測定できないため。 + /// </remarks> + private PerformanceRecorder perfRecOfResult; + /// <summary>UserInfo</summary> protected MyUserInfo UserInfo; + /// <summary>ログのユーザ名・IPアドレス部を生成する</summary> + /// <returns>",ユーザ名,IPアドレス"</returns> + /// <remarks> + /// Session が OFF の場合は UserInfo が null のままになり得るため、 + /// ログ出力が原因で例外を出さないよう null を考慮する。 + /// </remarks> + private string GetLogUserPart() + { + return "," + (this.UserInfo != null ? this.UserInfo.UserName : "") + + "," + (this.UserInfo != null ? this.UserInfo.IPAddress : ""); + } + #region OnAction ///// <summary> @@ -204,6 +237,129 @@ public override async Task OnActionExecutionAsync(ActionExecutingContext context #endregion + #region View + + /// <summary> + /// 応答にビューを表示する ViewResult オブジェクトを作成します。 + /// Controller.View メソッド (Microsoft.AspNetCore.Mvc) + /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.view + /// </summary> + /// <param name="viewName">ビュー名</param> + /// <param name="model">モデル</param> + /// <returns>ViewResult オブジェクト</returns> + /// <remarks> + /// net48 版はマスタ ページを取る View(IView, object) / View(string, string, object) を + /// オーバーライドしているが、ASP.NET Core にマスタ ページの概念は無い。 + /// Core では他の View オーバーロードが最終的に本メソッドへ集約されるため、ここだけで足りる。 + /// </remarks> + [NonAction] + public override ViewResult View(string viewName, object model) + { + ViewResult vr = base.View(viewName, model); + + // View() / View(model) で呼ばれた場合、ViewName は null になる + // (実行時にアクション名で解決されるため)。その場合はアクション名を使う。 + string vn = string.IsNullOrEmpty(vr.ViewName) ? this.ActionName : vr.ViewName; + string[] temp = vn.Split('.'); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + string strLogMessage = + this.GetLogUserPart() + + "," + "----->>" + + "," + this.ControllerName + + "," + this.ActionName + " -> " + temp[temp.Length - 1]; + + LogIF.InfoLog("ACCESS", strLogMessage); + + return vr; + } + + #endregion + + #region OnResult + + /// <summary> + /// アクション メソッドによって返されたアクション結果が実行される前に呼び出されます。 + /// Controller.OnResultExecuting メソッド (Microsoft.AspNetCore.Mvc) + /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.onresultexecuting + /// </summary> + /// <param name="context"> + /// 型: Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext + /// 現在の要求およびアクション結果に関する情報。 + /// </param> + public void OnResultExecuting(ResultExecutingContext context) + { + // 結果実行(レンダリング)区間の性能測定を開始する。 + this.perfRecOfResult = new PerformanceRecorder(); + this.perfRecOfResult.StartsPerformanceRecord(); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + string strLogMessage = + this.GetLogUserPart() + + "," + "----->" + + "," + this.ControllerName + + "," + this.ActionName + "(OnResultExecuting)"; + + LogIF.DebugLog("ACCESS", strLogMessage); + } + + /// <summary> + /// アクション メソッドによって返されたアクション結果が実行された後に呼び出されます。 + /// Controller.OnResultExecuted メソッド (Microsoft.AspNetCore.Mvc) + /// https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controller.onresultexecuted + /// </summary> + /// <param name="context"> + /// 型: Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext + /// 現在の要求およびアクション結果に関する情報。 + /// </param> + public void OnResultExecuted(ResultExecutedContext context) + { + // OnResultExecuting より前にエラーが発生した場合は、 + // perfRecOfResult が null の場合があるので、null 対策コードを挿入する。 + if (this.perfRecOfResult == null) + { + // null の場合、新しいインスタンスを生成し、性能測定開始。 + this.perfRecOfResult = new PerformanceRecorder(); + this.perfRecOfResult.StartsPerformanceRecord(); + } + + this.perfRecOfResult.EndsPerformanceRecord(); + + // ------------ + // メッセージ部 + // ------------ + // ユーザ名, IPアドレス, + // レイヤ, 画面名, コントロール名, 処理名 + // 処理時間(実行時間), 処理時間(CPU時間) + // エラーメッセージID, エラーメッセージ等 + // ------------ + string strLogMessage = + this.GetLogUserPart() + + "," + "<-----" + + "," + this.ControllerName + + "," + this.ActionName + "(OnResultExecuted)" + + "," + this.perfRecOfResult.ExecTime + + "," + this.perfRecOfResult.CpuTime; + + LogIF.DebugLog("ACCESS", strLogMessage); + } + + #endregion + #region 情報取得用 /// <summary>ユーザ情報を取得する</summary> diff --git a/root/programs/CS/Frameworks/Infrastructure/Directory.Build.props b/root/programs/CS/Frameworks/Infrastructure/Directory.Build.props new file mode 100644 index 000000000..99993561c --- /dev/null +++ b/root/programs/CS/Frameworks/Infrastructure/Directory.Build.props @@ -0,0 +1,50 @@ +<Project> + + <!-- + ********************************************************************************** + * ファイル名 :Directory.Build.props + * ファイル日本語名:Infrastructure 配下の共通ビルド プロパティ + * + * 作成者 :玄人 幸道 + * 更新履歴 : + * + * 日時 更新者 内容 + * 2026/07/31 玄人 幸道 新規作成(バージョン番号の一元管理) + ********************************************************************************** + + ■ 適用範囲 + 本ファイルは MSBuild が Microsoft.Common.props 経由で自動インポートするため、 + Infrastructure 配下の「SDK 形式」csproj(*_netcore100.csproj)にのみ適用される。 + 旧形式 csproj(*_net48.csproj、ToolsVersion=12.0)は Microsoft.Common.props を + インポートしないため影響を受けない。net48 のバージョンは従来どおり + 各プロジェクトの Properties\AssemblyInfo.cs が持つ。 + + ■ OpenTouryoVersion を変更したときに追随が必要な箇所 + (1) 各 *_net48.csproj の Properties\AssemblyInfo.cs の AssemblyVersion + (Public / Framework / Public.Security は 3.0.0.0。 + Business は意図的に 1.0.0.0 で別系統なので追随しない) + (2) NuGet パッケージ側は自動追随する。 + ..\..\NuGet\_NuGetPack.bat が本ファイルから値を読み取り、 + nuget pack に -Properties version=... として渡すため、 + nuspec 側は $version$ トークンのままでよい。 + + ■ 注意 + XML コメント内にハイフン 2 個の連続を書くと XML として不正になり、 + MSBuild がプロジェクトの読み込みに失敗する。区切り線に使わないこと。 + --> + + <PropertyGroup> + + <!-- ================================================================ + Open棟梁のリリース バージョン(唯一の定義箇所) + ここを書き換えれば、SDK 形式アセンブリと NuGet パッケージの + 双方に反映される。 + ================================================================ --> + <OpenTouryoVersion>3.0.0</OpenTouryoVersion> + + <!-- 全アセンブリ共通のメタデータ --> + <Company>Hitachi Solutions</Company> + + </PropertyGroup> + +</Project> diff --git a/root/programs/CS/Frameworks/Infrastructure/Framework/Framework_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Framework/Framework_netcore100.csproj index 97834fbad..27bd63b45 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Framework/Framework_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Framework/Framework_netcore100.csproj @@ -4,8 +4,7 @@ <TargetFramework>net10.0</TargetFramework> <RootNamespace>Touryo.Infrastructure.Framework</RootNamespace> <AssemblyName>OpenTouryo.Framework</AssemblyName> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Framework/RichClient/Framework.RichClient_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Framework/RichClient/Framework.RichClient_netcore100.csproj index 727448c34..7631e77f3 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Framework/RichClient/Framework.RichClient_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Framework/RichClient/Framework.RichClient_netcore100.csproj @@ -9,7 +9,7 @@ <StartupObject /> <RootNamespace>Touryo.Infrastructure.Framework.RichClient</RootNamespace> <AssemblyName>OpenTouryo.Framework.RichClient</AssemblyName> - <Version>3.0.0.0</Version> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetMessage.cs b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetMessage.cs index 008b0971c..5c5e2a11f 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetMessage.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetMessage.cs @@ -40,6 +40,8 @@ //* 2014/02/07 Rituparna Biswas Changes Made In GetMessageDescription for Internationalization //* 2014/02/19 西野 大介 取り込み(細かな修正) //* 2017/08/11 西野 大介 2014年のInternationalizationのrefactoringを実施 +//* 2026/08/01 玄人 幸道 定義ファイルの探索を ResourceLoader.ResolveFilePath に統一した。 +//* ※ 存在チェックと読み込みで同じ実パスを使うようにした。 //********************************************************************************** @@ -257,20 +259,30 @@ private static bool LoadFromFile(string filePath) return true; } - else if (ResourceLoader.Exists(filePath, false)) - { - XmlDocument xMLMSG = new XmlDocument(); - - // Load - xMLMSG.Load(StringVariableOperator.BuiltStringIntoEnvironmentVariable(filePath)); - // Save - GetMessage.DicMSG[filePath] = GetMessage.FillDictionary(xMLMSG); - - return true; - } else { - return false; + // ↓↓↓【変更】↓↓↓ + // リソース ローダで実パスを解決する。 + // ※ 以前は Exists で存在チェックした後、生のパスで開いていたため、 + // ResolveFilePath の探索結果(EXEの配置フォルダ基準)を活かせなかった。 + string msgFilePath = ResourceLoader.ResolveFilePath(filePath); + + if (msgFilePath != null) + { + XmlDocument xMLMSG = new XmlDocument(); + + // Load + xMLMSG.Load(msgFilePath); + // Save(キーは解決前のパス=設定値のまま) + GetMessage.DicMSG[filePath] = GetMessage.FillDictionary(xMLMSG); + + return true; + } + else + { + return false; + } + // ↑↑↑【変更】↑↑↑ } } diff --git a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetSharedProperty.cs b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetSharedProperty.cs index 817bc715f..8922ebaf1 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetSharedProperty.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Framework/Util/GetSharedProperty.cs @@ -1,4 +1,4 @@ -//********************************************************************************** +//********************************************************************************** //* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. //********************************************************************************** @@ -32,6 +32,8 @@ //* 2010/09/24 西野 大介 ジェネリック対応(XMLのDictionary化) //* nullチェック方法、Contains → ContainsKeyなどに注意 //* 2011/01/19 西野 大介 環境変数の組み込み処理に対応 +//* 2026/08/01 玄人 幸道 定義ファイルの探索を ResourceLoader.ResolveFilePath に統一した。 +//* ※ 存在チェックと読み込みで同じ実パスを使うようにした。 //********************************************************************************** using System; @@ -125,13 +127,17 @@ public SharedPropertyManager() #region リソース ローダでチェック(ここで落とすとハンドルされないので落とさない。) - if (ResourceLoader.Exists( - GetConfigParameter.GetConfigValue(FxLiteral.XML_SP_DEFINITION), false)) + // ↓↓↓【変更】↓↓↓ + // リソース ローダで実パスを解決する。 + // ※ 以前は Exists で存在チェックした後、生のパスで開いていたため、 + // ResolveFilePath の探索結果(EXEの配置フォルダ基準)を活かせなかった。 + string xmlSPFilePath = ResourceLoader.ResolveFilePath( + GetConfigParameter.GetConfigValue(FxLiteral.XML_SP_DEFINITION)); + + if (xmlSPFilePath != null) { // 共有情報定義(XmlDocument)を[リソース]で初期化 - xMLSP.Load( - StringVariableOperator.BuiltStringIntoEnvironmentVariable( - GetConfigParameter.GetConfigValue(FxLiteral.XML_SP_DEFINITION))); + xMLSP.Load(xmlSPFilePath); //// 戻す //return; @@ -140,6 +146,7 @@ public SharedPropertyManager() { // 何もしない。 } + // ↑↑↑【変更】↑↑↑ #endregion } diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamManagedOdp/DamManagedOdp_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamManagedOdp/DamManagedOdp_netcore100.csproj index 0b0636512..d8eb8ebdd 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamManagedOdp/DamManagedOdp_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamManagedOdp/DamManagedOdp_netcore100.csproj @@ -3,8 +3,7 @@ <TargetFramework>net10.0</TargetFramework> <AssemblyName>OpenTouryo.DamManagedOdp</AssemblyName> <RootNamespace>Touryo.Infrastructure.Public.Db</RootNamespace> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamMySQL/DamMySQL_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamMySQL/DamMySQL_netcore100.csproj index 30379dd39..ee81073ee 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamMySQL/DamMySQL_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamMySQL/DamMySQL_netcore100.csproj @@ -3,8 +3,7 @@ <TargetFramework>net10.0</TargetFramework> <AssemblyName>OpenTouryo.DamMySQL</AssemblyName> <RootNamespace>Touryo.Infrastructure.Public.Db</RootNamespace> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamPstGrS/DamPstGrS_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamPstGrS/DamPstGrS_netcore100.csproj index fbb9b1028..f644bd0d6 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamPstGrS/DamPstGrS_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Db/DamPstGrS/DamPstGrS_netcore100.csproj @@ -3,8 +3,7 @@ <TargetFramework>net10.0</TargetFramework> <AssemblyName>OpenTouryo.DamPstGrS</AssemblyName> <RootNamespace>Touryo.Infrastructure.Public.Db</RootNamespace> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Db/SQLUtility.cs b/root/programs/CS/Frameworks/Infrastructure/Public/Db/SQLUtility.cs index 9eff8bfec..b4199995c 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Db/SQLUtility.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Db/SQLUtility.cs @@ -35,6 +35,7 @@ //* 2014/01/30 Sai Krishna added code for batch processing supporting MySQL //* 2014/01/30 Santoshkumar added code for batch processing supporting DB2 //* 2014/03/04 Santoshkumar Modified code for converting char data type for batch processing supporting DB2 and Oracle +//* 2026/08/02 玄人 幸道 GetUpdateSQLParts:複合主キーで誤ったUPDATE文を生成する問題を修正 //********************************************************************************** using System; @@ -373,50 +374,100 @@ public string[] GetUpdateSQLParts(DataTable dt, string[] primaryKeys) } } - // As per the PostGreSQL and MySQL syntax for batch update - // we have to use a "CASE ... WHEN ... THEN" while updating multiple records. + // 生成できないケースは、ここで打ち切る(DBMSによらず共通)。 + // + // ・更新対象列が無い … SET句が空のSQLは構文エラーになる。 + // ・主キーが無い … 行を特定できず、WHERE句が無いと全行更新になる。 + // + // 打ち切らずに進むと、末尾の切り詰め処理が初期値のStringBuilderを削るため、 + // "SE" や "WH" といった壊れた文字列を返してしまう。 + if (colSet.Count == 0 || colWhere.Count == 0) + { + return list.ToArray(); + } + + // PostgreSQL・MySQLには、1文で複数行を別々の値に更新する構文が無いため、 + // 「CASE ... WHEN ... THEN」で行ごとの値を切り替える。 + // 他のDBMS(else側)は1行1文を行数分returnするが、こちらは1文にまとめる。 + // + // <生成される UPDATE 文の全体像> + // + // 本メソッドが返すのは "SET ... WHERE ..." の部分のみで、 + // 呼び出し側が "UPDATE <テーブル名>" を前置して1文を組み立てる。 + // + // UPDATE "Orders" ← 呼び出し側が付与 + // SET "Qty" = CASE + // WHEN "OrderID" = 1 AND "ProductID" = 10 THEN 100 + // WHEN "OrderID" = 2 AND "ProductID" = 20 THEN 200 + // ELSE "Qty" ← 対象外の行は現状維持 + // END, + // "Note" = CASE + // WHEN "OrderID" = 1 AND "ProductID" = 10 THEN 'a' + // WHEN "OrderID" = 2 AND "ProductID" = 20 THEN 'b' + // ELSE "Note" + // END + // WHERE ("OrderID" = 1 AND "ProductID" = 10) ← 主キーの組み合わせで絞る + // OR ("OrderID" = 2 AND "ProductID" = 20) + // + // <構造> + // ・更新対象列(主キー以外)ごとに CASE 式を1つ作る。 + // ・CASE の WHEN は入力DataTableの行数分並び、行を主キーで特定して値を与える。 + // ・WHERE は同じ主キーの組み合わせをORで並べ、更新対象の行だけに限定する。 + // + // <複合主キーの扱い> + // 主キーが複数列ある場合、WHEN も WHERE も「列ごとに独立」ではなく + // 「組み合わせ(AND)」で判定しなければならない。 + // 列ごとに独立させると、WHERE が直積になって更新対象でない行に一致し、 + // さらに CASE も先に一致した枝が勝つため、誤った行に誤った値が入る。 + // + // <ELSE を付ける理由> + // CASE はどの WHEN にも一致しないと NULL を返す。 + // WHERE で対象行に限定しているため通常は一致するが、 + // NULL 上書きという最悪の失敗を避けるため、保険として自身の列を指定する。 if (this._dbms == DbEnum.DBMSType.PstGrS || this._dbms == DbEnum.DBMSType.MySQL) { sbSet = new StringBuilder("SET "); sbWhere = new StringBuilder("\r\nWHERE "); - int count = 0; - // 更新対象列 + // 更新対象列(主キー以外)ごとに CASE 式を作る。 + bool isFirstSet = true; foreach (string set in colSet) { - sbSet.Append(set + " = CASE"); + if (!isFirstSet) + { + sbSet.Append(",\r\n "); + } + isFirstSet = false; - foreach (string where in colWhere) + sbSet.Append(this.OpeningBracket + set + this.ClosingBracket + " = CASE"); + + // 行ごとに「主キーの組み合わせ = その行の値」を条件とする。 + foreach (DataRow dr in dt.Rows) { - if (count < colWhere.Count) - sbWhere.Append(where + " IN ("); - foreach (DataRow dr in dt.Rows) - { - sbSet.Append( - " WHEN " + where + " =" + this.ConvertParameterToSQL(dr[where]) - + " THEN " + this.ConvertParameterToSQL(dr[set]) + "\r\n"); + sbSet.Append("\r\n WHEN " + this.GetPrimaryKeyCondition(dr, colWhere) + + " THEN " + this.ConvertParameterToSQL(dr[set])); + } - // パラメタをSQLに変換する。 - if (count < colWhere.Count) - sbWhere.Append(this.ConvertParameterToSQL(dr[where]) + ", "); - } - // Sharpen last comma and AND - if (count < colWhere.Count) - { - sbWhere.Remove((sbWhere.Length - 2), 2); - sbWhere.Append(") AND "); - } - count++; + // どのWHENにも一致しない行は、現在の値を保つ。 + sbSet.Append("\r\n ELSE " + this.OpeningBracket + set + this.ClosingBracket); + sbSet.Append("\r\n END"); + } + + // WHERE は主キーの組み合わせをORで並べ、更新対象の行だけに限定する。 + bool isFirstWhere = true; + foreach (DataRow dr in dt.Rows) + { + if (!isFirstWhere) + { + sbWhere.Append("\r\n OR "); } - // Adding END to the CASE - sbSet.Append(" END,\r\n"); + isFirstWhere = false; + + sbWhere.Append("(" + this.GetPrimaryKeyCondition(dr, colWhere) + ")"); } - // Removing Last AND. - tempWhere = sbWhere.ToString().Substring(0, sbWhere.Length - 4); tempSet = sbSet.ToString(); - // Removing Last END. - tempSet = tempSet.Substring(0, tempSet.Length - 3); + tempWhere = sbWhere.ToString(); // 結合して追加。 list.Add(tempSet + " " + tempWhere); @@ -464,6 +515,34 @@ public string[] GetUpdateSQLParts(DataTable dt, string[] primaryKeys) return list.ToArray(); } + /// <summary>1行を特定する主キーの条件式を生成する。</summary> + /// <param name="dr">対象行</param> + /// <param name="primaryKeys">主キー列名のリスト</param> + /// <returns>条件式(例: "OrderID" = 1 AND "ProductID" = 10 )</returns> + /// <remarks> + /// 複合主キーの場合は、列ごとに独立させず AND で結合する。 + /// 独立させると行を一意に特定できず、意図しない行に一致する。 + /// </remarks> + private string GetPrimaryKeyCondition(DataRow dr, List<string> primaryKeys) + { + StringBuilder sb = new StringBuilder(); + + bool isFirst = true; + foreach (string pk in primaryKeys) + { + if (!isFirst) + { + sb.Append(" AND "); + } + isFirst = false; + + sb.Append(this.OpeningBracket + pk + this.ClosingBracket + + " = " + this.ConvertParameterToSQL(dr[pk])); + } + + return sb.ToString(); + } + /// <summary>パラメタをSQLに変換する。</summary> /// <param name="obj">パラメタ</param> /// <returns>SQL化したパラメタ</returns> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/IO/ResourceLoader.cs b/root/programs/CS/Frameworks/Infrastructure/Public/IO/ResourceLoader.cs index 54c9830ab..8bc9b932c 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/IO/ResourceLoader.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/IO/ResourceLoader.cs @@ -30,6 +30,10 @@ //* 2007/xx/xx 西野 大介 新規作成 //* 2009/03/13 西野 大介 存在チェック処理メソッドを追加 //* 2011/01/14 西野 大介 環境変数の組み込み処理に対応 +//* 2026/08/01 玄人 幸道 ResolveFilePathメソッドを追加し、探索処理を集約した。 +//* 相対パスがカレント ディレクトリ基準で見つからない場合、 +//* AppContext.BaseDirectory(EXEの配置フォルダ)基準で再探索する。 +//* ※ CLIが任意のカレント ディレクトリから起動される問題への対応。 //********************************************************************************** using System; @@ -46,6 +50,59 @@ namespace Touryo.Infrastructure.Public.IO /// <remarks>自由に利用できる。</remarks> public static class ResourceLoader { + // ↓↓↓【追加】↓↓↓ + + #region パス解決 + + /// <summary>[リソース ファイル]の実パスを解決する</summary> + /// <param name="loadfilepath">[リソース ファイル]へのパス</param> + /// <returns>見つかった実パス。見つからない場合は null。</returns> + /// <remarks> + /// 自由に利用できる。 + /// 探索順は下記のとおり。 + /// (1) 指定されたパス(絶対パス、または カレント ディレクトリ基準の相対パス) + /// (2) AppContext.BaseDirectory(EXEの配置フォルダ)基準の相対パス + /// (1) を優先するため、従来動作していた構成の挙動は変わらない。 + /// (2) は、CLIが任意のカレント ディレクトリから起動される場合への対応。 + /// ※ AppContext.BaseDirectoryは、PublishSingleFile(単一ファイル発行)でも + /// 正しい値を返す(Assembly.Locationは空文字になるため使用しない)。 + /// </remarks> + public static string ResolveFilePath(string loadfilepath) + { + // 環境変数の組み込み処理に対応 + loadfilepath = StringVariableOperator.BuiltStringIntoEnvironmentVariable(loadfilepath); + + if (string.IsNullOrEmpty(loadfilepath)) + { + // 指定なし + return null; + } + + // (1) 指定されたパスで探す。 + if (File.Exists(loadfilepath)) + { + return loadfilepath; + } + + // (2) 見つからない場合、EXEの配置フォルダ基準で探す(相対パスの場合のみ)。 + if (!Path.IsPathRooted(loadfilepath)) + { + string loadfilepath2 = Path.Combine(AppContext.BaseDirectory, loadfilepath); + + if (File.Exists(loadfilepath2)) + { + return loadfilepath2; + } + } + + // 見つからない。 + return null; + } + + #endregion + + // ↑↑↑【追加】↑↑↑ + #region 存在チェック /// <summary>存在チェックのみのメソッド</summary> @@ -55,11 +112,8 @@ public static class ResourceLoader /// <remarks>自由に利用できる。</remarks> public static bool Exists(string loadfilepath, bool throwException) { - // 環境変数の組み込み処理に対応 - loadfilepath = StringVariableOperator.BuiltStringIntoEnvironmentVariable(loadfilepath); - - // 存在チェック - if (File.Exists(loadfilepath)) + // 存在チェック(【変更】探索処理を ResolveFilePath に集約した) + if (ResourceLoader.ResolveFilePath(loadfilepath) != null) { // 存在する。 return true; @@ -90,28 +144,8 @@ public static bool Exists(string filePath, string fileName, bool throwException) // パス文字結合 string loadfilepath = Path.Combine(filePath, fileName); - // 環境変数の組み込み処理に対応 - loadfilepath = StringVariableOperator.BuiltStringIntoEnvironmentVariable(loadfilepath); - - // 存在チェック - if (File.Exists(loadfilepath)) - { - // 存在する。 - return true; - } - else - { - // 存在しない。 - if (throwException) - { - throw new ArgumentException(String.Format( - PublicExceptionMessage.RESOURCE_FILE_NOT_FOUND, loadfilepath)); - } - else - { - return false; - } - } + // 存在チェック(【変更】探索処理を ResolveFilePath に集約した) + return ResourceLoader.Exists(loadfilepath, throwException); } #endregion @@ -125,15 +159,15 @@ public static bool Exists(string filePath, string fileName, bool throwException) /// <remarks>自由に利用できる。</remarks> public static string LoadAsString(string loadfilepath, Encoding enc) { - // 環境変数の組み込み処理に対応 - loadfilepath = StringVariableOperator.BuiltStringIntoEnvironmentVariable(loadfilepath); + // 存在チェック(【変更】探索処理を ResolveFilePath に集約した) + string resolvedPath = ResourceLoader.ResolveFilePath(loadfilepath); StreamReader sr = null; try { // 存在チェック - if (File.Exists(loadfilepath)) + if (resolvedPath != null) { // 存在する。 } @@ -145,7 +179,7 @@ public static string LoadAsString(string loadfilepath, Encoding enc) } // 開く - sr = new StreamReader(loadfilepath, enc); + sr = new StreamReader(resolvedPath, enc); // 読む return sr.ReadToEnd(); @@ -176,15 +210,15 @@ public static string LoadAsString(string filePath, string fileName, Encoding enc // パス文字結合 string loadfilepath = Path.Combine(filePath, fileName); - // 環境変数の組み込み処理に対応 - loadfilepath = StringVariableOperator.BuiltStringIntoEnvironmentVariable(loadfilepath); + // 存在チェック(【変更】探索処理を ResolveFilePath に集約した) + string resolvedPath = ResourceLoader.ResolveFilePath(loadfilepath); StreamReader sr = null; try { // 存在チェック - if (File.Exists(loadfilepath)) + if (resolvedPath != null) { // 存在する。 } @@ -196,7 +230,7 @@ public static string LoadAsString(string filePath, string fileName, Encoding enc } // 開く - sr = new StreamReader(loadfilepath, enc); + sr = new StreamReader(resolvedPath, enc); // 読む return sr.ReadToEnd(); diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_log4net.cs b/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_log4net.cs index 976884180..522af06c3 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_log4net.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_log4net.cs @@ -1,4 +1,4 @@ -//********************************************************************************** +//********************************************************************************** //* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. //********************************************************************************** @@ -38,6 +38,8 @@ //* 2011/01/19 西野 大介 環境変数の組み込み処理に対応 //* 2011/10/09 西野 大介 国際化対応 //* 2018/03/28 西野 大介 .NET Standard対応で、I/F変更あり。 +//* 2026/08/01 玄人 幸道 定義ファイルの探索を ResourceLoader.ResolveFilePath に統一した。 +//* ※ 存在チェックと読み込みで同じ実パスを使うようにした。 //********************************************************************************** using System; @@ -154,13 +156,23 @@ public static log4net.ILog GetLog4netIf(string loggerName) } else { - // リソース ローダで存在チェック(存在しなければエラー) - ResourceLoader.Exists(log4netConfFile, true); + // ↓↓↓【変更】↓↓↓ + // リソース ローダで実パスを解決する。 + // ※ 以前は Exists で存在チェックした後、生のパスで開いていたため、 + // ResolveFilePath の探索結果(EXEの配置フォルダ基準)を活かせなかった。 + string log4netConfFilePath = ResourceLoader.ResolveFilePath(log4netConfFile); + + if (log4netConfFilePath == null) + { + // 存在しない場合はエラー(例外の送出は Exists に委ねる) + ResourceLoader.Exists(log4netConfFile, true); + } // ログ定義 [リソース ファイル] → ストリームを開く FileStream s = new FileStream( - StringVariableOperator.BuiltStringIntoEnvironmentVariable(log4netConfFile), + log4netConfFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); + // ↑↑↑【変更】↑↑↑ // log4netのXML形式の設定ファイルを読み込む。 #if (NETSTD || NETCOREAPP) diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_nlog.cs b/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_nlog.cs index e56b337d1..fab4dd14d 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_nlog.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Log/LogManager_nlog.cs @@ -1,4 +1,4 @@ -//********************************************************************************** +//********************************************************************************** //* Copyright (C) 2007,2016 Hitachi Solutions,Ltd. //********************************************************************************** @@ -28,6 +28,8 @@ //* 日時 更新者 内容 //* ---------- ---------------- ------------------------------------------------- //* 2025/06/15 西野 大介 新規作成 +//* 2026/08/01 玄人 幸道 定義ファイルの探索を ResourceLoader.ResolveFilePath に統一した。 +//* ※ 存在チェックと読み込みで同じ実パスを使うようにした。 //********************************************************************************** using System; @@ -127,11 +129,21 @@ public static NLog.Logger GetNLogIf(string loggerName) } else { - // リソース ローダで存在チェック(存在しなければエラー) - ResourceLoader.Exists(nlogConfFile, true); + // ↓↓↓【変更】↓↓↓ + // リソース ローダで実パスを解決する。 + // ※ 以前は Exists で存在チェックした後、生のパスで開いていたため、 + // ResolveFilePath の探索結果(EXEの配置フォルダ基準)を活かせなかった。 + string nlogConfFilePath = ResourceLoader.ResolveFilePath(nlogConfFile); + + if (nlogConfFilePath == null) + { + // 存在しない場合はエラー(例外の送出は Exists に委ねる) + ResourceLoader.Exists(nlogConfFile, true); + } // nlog - NLog.LogManager.Configuration = new XmlLoggingConfiguration(nlogConfFile); + NLog.LogManager.Configuration = new XmlLoggingConfiguration(nlogConfFilePath); + // ↑↑↑【変更】↑↑↑ } // NLog.Loggerインスタンスを初期化する。 diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Public_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Public_netcore100.csproj index 8f7bce691..ecc58324b 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Public_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Public_netcore100.csproj @@ -4,8 +4,7 @@ <TargetFramework>net10.0</TargetFramework> <AssemblyName>OpenTouryo.Public</AssemblyName> <RootNamespace>Touryo.Infrastructure.Public</RootNamespace> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Jwt/EccPublicKeyConverter.cs b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Jwt/EccPublicKeyConverter.cs index 86fea6e49..49bcf7034 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Jwt/EccPublicKeyConverter.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Jwt/EccPublicKeyConverter.cs @@ -32,6 +32,8 @@ //* 下位がExportableである必要性があった、 //* また、ASP.NET上で実行する可能性もある。 //* 2019/06/25 西野 大介 インスタンス・メソッド化(ES256, 384, 512対応) +//* 2026/08/01 玄人 幸道 jose-jwtへの依存を解消(JwkToCngをBCLのみで実装) +//* ※ 楕円曲線の決定にcrvを使用するため、jose-jwt非互換。 //********************************************************************************** using System; @@ -44,7 +46,6 @@ //using Jose; //using Security.Cryptography; -using Jose.keys; using Touryo.Infrastructure.Public.Str; @@ -252,14 +253,34 @@ public CngKey JwkToCng(string jwkString) /// <summary>JwkToCng</summary> /// <param name="jwk">JObject</param> /// <returns>CngKey(公開鍵)</returns> + /// <remarks> + /// 【jose-jwt 非互換】 + /// 以前は jose-jwt の EccKey.New(x, y) を使用していたが、 + /// jose-jwt への依存を解消するため、BCL のみの実装に変更した。 + /// これに伴い、楕円曲線の決定方法が変わっている。 + /// ・旧:x 座標のバイト長から推測(32→P-256、48→P-384、66→P-521) + /// ・新:JWK の crv メンバを参照する + /// 長さによる推測は secp256k1 や Brainpool と区別が付かず、 + /// 誤った曲線の鍵を生成し得るため、crv を必須とした。 + /// なお crv は RFC 7517/RFC 7518 において EC 鍵の必須メンバであり、 + /// 姉妹メソッドの JwkToParam も従来から crv を必須としている。 + /// </remarks> public CngKey JwkToCng(Dictionary<string, string> jwk) { + ECParameters ecParams = new ECParameters(); + // 楕円曲線 - // 不要 + ecParams.Curve = this.GetECCurveFromCrvString((string)jwk[JwtConst.crv]); + // 公開鍵の部分 - return EccKey.New( - CustomEncode.FromBase64UrlString((string)jwk[JwtConst.x]), - CustomEncode.FromBase64UrlString((string)jwk[JwtConst.y])); + ecParams.Q.X = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.x]); + ecParams.Q.Y = CustomEncode.FromBase64UrlString((string)jwk[JwtConst.y]); + + // ECParameters → CngKey + ECDsaCng ecDsaCng = new ECDsaCng(); + ecDsaCng.ImportParameters(ecParams); + + return ecDsaCng.Key; } #endregion diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_net48.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_net48.csproj index 4cbe5694a..8a44e3a58 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_net48.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_net48.csproj @@ -184,9 +184,6 @@ <PackageReference Include="BouncyCastle.NetCore"> <Version>2.2.1</Version> </PackageReference> - <PackageReference Include="jose-jwt"> - <Version>5.1.1</Version> - </PackageReference> <PackageReference Include="Newtonsoft.Json"> <Version>13.0.3</Version> </PackageReference> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_netcore100.csproj b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_netcore100.csproj index ae0d5e251..7c76f1ef4 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_netcore100.csproj +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Security/Public.Security_netcore100.csproj @@ -4,8 +4,7 @@ <TargetFramework>net10.0</TargetFramework> <AssemblyName>OpenTouryo.Public.Security</AssemblyName> <RootNamespace>Touryo.Infrastructure.Public.Security</RootNamespace> - <Version>3.0.0.0</Version> - <Company>Hitachi Solutions</Company> + <Version>$(OpenTouryoVersion)</Version> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> @@ -38,7 +37,6 @@ <ItemGroup> <PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" /> - <PackageReference Include="jose-jwt" Version="5.1.1" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="System.Security.Cryptography.Xml" Version="9.0.15" /> </ItemGroup> diff --git a/root/programs/CS/Frameworks/Infrastructure/Public/Util/GetConfigParameter.cs b/root/programs/CS/Frameworks/Infrastructure/Public/Util/GetConfigParameter.cs index b2367aae8..97332059f 100644 --- a/root/programs/CS/Frameworks/Infrastructure/Public/Util/GetConfigParameter.cs +++ b/root/programs/CS/Frameworks/Infrastructure/Public/Util/GetConfigParameter.cs @@ -36,6 +36,11 @@ //* ※ JSONキーの「:」を「__」で処理する。 //* GetAnyConfigSectionメソッドでコンテナ・モードに対応しない。 //* ※ コンテナ・モードでは、セクションを返せない。 +//* 2026/08/01 玄人 幸道 appsettings.jsonの読込基点を、currentディレクトリから +//* AppContext.BaseDirectory(EXEの配置フォルダ)に変更した。 +//* ※ app.configと同じ挙動に揃え、CLIのカレント依存を解消する。 +//* 2026/08/01 玄人 幸道 埋め込まれたリソースから初期化するオーバーロードを追加した。 +//* ※ PublishSingleFile(単一ファイル発行)への対応。 //********************************************************************************** #if (NETSTD || NETCOREAPP) @@ -86,27 +91,60 @@ public static void InitConfiguration(IConfigurationBuilder builder) /// <summary>IConfigurationの初期化</summary> /// <param name="jsonFileName">string</param> + /// <remarks> + /// jsonFileNameに絶対パスを指定した場合は、そのパスが優先される。 + /// </remarks> public static void InitConfiguration(string jsonFileName) { IConfigurationBuilder builder = new ConfigurationBuilder(); - // currentディレクトリのappsettings.jsonを読み込む。 + // ↓↓↓【変更】↓↓↓ + // EXEの配置フォルダのappsettings.jsonを読み込む。 + // 以前はcurrentディレクトリを基点にしていたが、CLIは任意のカレント + // ディレクトリから起動されるため、読み込みに失敗することがあった。 + // ※ app.config(<exe名>.exe.config)と同じ、EXEの隣を見る挙動に揃えている。 + // ※ AppContext.BaseDirectoryは、PublishSingleFile(単一ファイル発行)でも + // 正しい値を返す(Assembly.Locationは空文字になるため使用しない)。 builder = builder - .SetBasePath(Directory.GetCurrentDirectory()) + .SetBasePath(AppContext.BaseDirectory) .AddJsonFile(jsonFileName); + // ↑↑↑【変更】↑↑↑ GetConfigParameter._configuration = builder.Build(); } + // ↓↓↓【追加】↓↓↓ + + /// <summary>IConfigurationの初期化(埋め込まれたリソース)</summary> + /// <param name="jsonStream">Stream</param> + /// <remarks> + /// PublishSingleFile(単一ファイル発行)などで、appsettings.jsonを + /// EXEの隣に配置できない場合に使用する。 + /// EmbeddedResourceLoader.LoadAsStreamの戻り値を渡す。 + /// </remarks> + public static void InitConfiguration(Stream jsonStream) + { + IConfigurationBuilder builder = new ConfigurationBuilder(); + + // 埋め込まれたリソースのappsettings.jsonを読み込む。 + builder = builder.AddJsonStream(jsonStream); + + GetConfigParameter._configuration = builder.Build(); + } + + // ↑↑↑【追加】↑↑↑ + /// <summary>IConfigurationの初期化</summary> public static void InitConfiguration() { IConfigurationBuilder builder = new ConfigurationBuilder(); - // currentディレクトリのappsettings.jsonを読み込む。 + // ↓↓↓【変更】↓↓↓ + // EXEの配置フォルダのappsettings.jsonを読み込む(理由は上記と同じ)。 builder = builder - .SetBasePath(Directory.GetCurrentDirectory()) + .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("appsettings.json"); + // ↑↑↑【変更】↑↑↑ #region 参考:メモリ内プロバイダによる POCO クラスとのバインディング diff --git a/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/Result48.txt b/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/Result48.txt index 6d53435aa..48d1d2f4d 100644 --- a/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/Result48.txt +++ b/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/Result48.txt @@ -82,8 +82,8 @@ JWS_RS256_X509.Verify > True JWS_RS256_Param.Verify > True jWS_RS384_XML.Create > JWS Header: {"alg":"RS384","typ":"JWT"} jWS_RS384_XML.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -jWS_RS384_XML.Create > JWS Signature: GYtiAAj6L44GHM2qypvONV8lNM2OPtwrTnfYD6j5Q9lyIHWP6h0iK9bp3TNno_-A63xosowbWK3IuyMx1FKsu2IqLiyjjBwp7jsE8UbOlPF2usFizii_5hgiVYVAXos7A0VdbTs8A0bINjGjh4cH3yPAXzHKsD4-6hYANWilod8 -RSA JWK > {"kty":"RSA","alg":"RS384","n":"vBRhj9ifBc_zAm5kkH9KOMKf1m_xrbXpkaMsFw_ZZtl3kD-fQzquUd04E7-OAbbe5xj4W1O_ec2w4ODqdcZGeD4vCqr9aiO04a3iPyncdPq07in2Va_gUa8VGJZPrOv25tt2vDvLeY9gs4COgPpvem39kgBaPSrdZ5wi6t8P3TE","e":"AQAB","kid":"ckOA08yMty7xvdwDUtRWO28qoilvZssjrj41DONhyGOT6FY5aN-nLsTp02_Co08c"} +jWS_RS384_XML.Create > JWS Signature: MMUX9SZqXEz5wevRRdpE3hmY7PxEBFqlwBwrQAAG67Lp9phWUHs8__SECqt2clnASw-4L4USaRRB1ZoXREISAmozj5AQUdRURsPUOB4m7mQtXUWheY35vN3VSaU-rH_r8O42o9WjW1wQmNHwk7UjXlKU9pgLtVj2eEn0x2qRc5o +RSA JWK > {"kty":"RSA","alg":"RS384","n":"xRj4g7Vh2gbBX6hKL0lYO4f2fgvfe9rm8TRVM9TOuVR-OIaCRVFBki3j4K6JY0qF-yucHuULbGlrvXtrcFEx9z4owIc0QO8Ot5wpGwsg3nNWKBYXasZis27IxfNgS8DRQRUVX_toBCc7H_kU59u1iGyVeAiyVaWpbusYMilIJY0","e":"AQAB","kid":"8T4Bg-5umKnbgbUsomWJfdzdS6dWUTneDncu-BRaCI9iBwa_I5gBgUZMR41KRAYz"} JWS_RS384_XML.Verify > True JWS_RS384_Param.Verify > True JWS_RS512_X509.Create > JWS Header: {"alg":"RS512","typ":"JWT"} @@ -94,54 +94,54 @@ JWS_RS512_X509.Verify > True JWS_RS512_Param.Verify > True JWS_ES256_X509.Create > JWS Header: {"alg":"ES256","typ":"JWT"} JWS_ES256_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES256_X509.Create > JWS Signature: bDS8uIGDfDIuYcOOiEbl0GsEVSUNSl22y1vXERK_KbORH2VdJVdULkxkBXw15fMfRrGYUQkVWwlKW3EdkQ1rPg +JWS_ES256_X509.Create > JWS Signature: ZTWQ13rPVQAjrmlFpTO02tjPx4otIN_vgTIVVKlZdDuFiwl840lt0HU7m7w9u38WamcOv_WzHR-eqFdYWO-iSA ECDSA JWK > {"kty":"EC","alg":"ES256","crv":"P-256","x":"qdS3bsts3UXi5p0G71GofUB9ls1fJz_z0dRQw9RZ99A","y":"hX6HISTIiDLt90VDEqGmsMj2kSlGLOcXgXSqz75EhV4","kid":"asm1SGqVczG7zj0saZPKiggv2xwRlb6c23CDCNBqBNA"} JWS_ES256_X509.Verify > True JWS_ES256_Param.Verify > True -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.bDS8uIGDfDIuYcOOiEbl0GsEVSUNSl22y1vXERK_KbORH2VdJVdULkxkBXw15fMfRrGYUQkVWwlKW3EdkQ1rPg +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.ZTWQ13rPVQAjrmlFpTO02tjPx4otIN_vgTIVVKlZdDuFiwl840lt0HU7m7w9u38WamcOv_WzHR-eqFdYWO-iSA JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: bDS8uIGDfDIuYcOOiEbl0GsEVSUNSl22y1vXERK_KbORH2VdJVdULkxkBXw15fMfRrGYUQkVWwlKW3EdkQ1rPg +JwsAlgorithm.xLibTest > JWS Signature: ZTWQ13rPVQAjrmlFpTO02tjPx4otIN_vgTIVVKlZdDuFiwl840lt0HU7m7w9u38WamcOv_WzHR-eqFdYWO-iSA JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWS_ES384_X509.Create > JWS Header: {"alg":"ES384","typ":"JWT"} JWS_ES384_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES384_X509.Create > JWS Signature: Mqm-d-FC7NZ9bniVD9UYcnMJe5pJB-Hi_Kff18AyZ068k3aDac_Rb8ijEXf0TYJLTrbl-E6ToPpgfK7N0VZxPy1sFMygZDAIi_D40jwTFqJXmaplMFhAnt6bACQG7mby +JWS_ES384_X509.Create > JWS Signature: Uz9GiL_gpaRdd2_ni-scazbO24Uu1nE3N5gyiMHAloEPNTmBj9w7lLfOAd4sCShClEM0FJVDEvdVSin8Cvkp98KCG5vndr9hteQPbpG3HdGtwsU9InheMrjmCnPsbC3Q JWS_ES384_X509.Verify > True ECDSA JWK > {"kty":"EC","alg":"ES384","crv":"P-384","x":"qeyd2iMw8DZT7Yy3KO0mOuok1JBBdMwEuJTa81Upg06fbVbotK8yuhDSVkzSFsw3","y":"thH6faasSDmEO4zeVNdc5LbZJprQmL7JN3NZzYUJmF1GhQEl6QaZh-6f1QhDH0St","kid":"e_kI1ZJ_x9ttzEU_DICgGhJeNK8ghcW3bSl7KFM6eVefpKJHA5ecCowzJw69r9Vr"} JWS_ES384_X509.Verify > True JWS_ES384_Param.Verify > False -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.Mqm-d-FC7NZ9bniVD9UYcnMJe5pJB-Hi_Kff18AyZ068k3aDac_Rb8ijEXf0TYJLTrbl-E6ToPpgfK7N0VZxPy1sFMygZDAIi_D40jwTFqJXmaplMFhAnt6bACQG7mby +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.Uz9GiL_gpaRdd2_ni-scazbO24Uu1nE3N5gyiMHAloEPNTmBj9w7lLfOAd4sCShClEM0FJVDEvdVSin8Cvkp98KCG5vndr9hteQPbpG3HdGtwsU9InheMrjmCnPsbC3Q JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES384","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: Mqm-d-FC7NZ9bniVD9UYcnMJe5pJB-Hi_Kff18AyZ068k3aDac_Rb8ijEXf0TYJLTrbl-E6ToPpgfK7N0VZxPy1sFMygZDAIi_D40jwTFqJXmaplMFhAnt6bACQG7mby +JwsAlgorithm.xLibTest > JWS Signature: Uz9GiL_gpaRdd2_ni-scazbO24Uu1nE3N5gyiMHAloEPNTmBj9w7lLfOAd4sCShClEM0FJVDEvdVSin8Cvkp98KCG5vndr9hteQPbpG3HdGtwsU9InheMrjmCnPsbC3Q JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWS_ES512_X509.Create > JWS Header: {"alg":"ES512","typ":"JWT"} JWS_ES512_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES512_X509.Create > JWS Signature: AJxgTQH_qS55UyUyYSrNG1G5bfnU_g8qto77lsWSLRSqgGzK5aIhYz1jBx3doDJTEmDthiB7Ane52TvOnj_XnIIIAG-iGaMKlEEbyS0S6esD7pRcp7wUuAp1iZt-GTY9d_xN1wKayxJPw-T2H7fXGzq8YgF2doLvP5YSdIHiLzYm4n9E +JWS_ES512_X509.Create > JWS Signature: AcZClXTSsO9nyhWu8iuXF02F-mLVDN86jKOJjpbcm5baIqKkZt0iuPGsBo_qZcz5beT9GCpkkO2IF8Vnw-NLyL_YAYmUsvNXEZugRJ4xsd3Tn6RO1UX1lCjINMt235WGkYJQHpGw4cuuzR46HKnVp1sNkoy63hQV5y94GmM7W22pu4yP JWS_ES512_X509.Verify > True ECDSA JWK > {"kty":"EC","alg":"ES512","crv":"P-521","x":"AQoRdSDzXLfin6CFhLxDOL0_Cfn-QcwgdbMkMGgwTeA4gDIygCOEy4m0eyTmEnjYdBOMN5JtYUiprdZZriAGzrHC","y":"ATj5JBej9ztfsArJLUMCs4edyCgPuItefh7KFGfeefI7YjB-pakcKxzhHZ1h2UhR183bnQ4rrXc71N5WAl3d5BqZ","kid":"OaO51pUD4-aJ8skED2eag0nvd1kfqIwo9BhB86PEZ34PBLE4TiHv6v9LCK20r0c6x06bULLSi84PcldSN2n6DQ"} JWS_ES512_X509.Verify > True JWS_ES512_Param.Verify > False -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.AJxgTQH_qS55UyUyYSrNG1G5bfnU_g8qto77lsWSLRSqgGzK5aIhYz1jBx3doDJTEmDthiB7Ane52TvOnj_XnIIIAG-iGaMKlEEbyS0S6esD7pRcp7wUuAp1iZt-GTY9d_xN1wKayxJPw-T2H7fXGzq8YgF2doLvP5YSdIHiLzYm4n9E +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.AcZClXTSsO9nyhWu8iuXF02F-mLVDN86jKOJjpbcm5baIqKkZt0iuPGsBo_qZcz5beT9GCpkkO2IF8Vnw-NLyL_YAYmUsvNXEZugRJ4xsd3Tn6RO1UX1lCjINMt235WGkYJQHpGw4cuuzR46HKnVp1sNkoy63hQV5y94GmM7W22pu4yP JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES512","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: AJxgTQH_qS55UyUyYSrNG1G5bfnU_g8qto77lsWSLRSqgGzK5aIhYz1jBx3doDJTEmDthiB7Ane52TvOnj_XnIIIAG-iGaMKlEEbyS0S6esD7pRcp7wUuAp1iZt-GTY9d_xN1wKayxJPw-T2H7fXGzq8YgF2doLvP5YSdIHiLzYm4n9E +JwsAlgorithm.xLibTest > JWS Signature: AcZClXTSsO9nyhWu8iuXF02F-mLVDN86jKOJjpbcm5baIqKkZt0iuPGsBo_qZcz5beT9GCpkkO2IF8Vnw-NLyL_YAYmUsvNXEZugRJ4xsd3Tn6RO1UX1lCjINMt235WGkYJQHpGw4cuuzR46HKnVp1sNkoy63hQV5y94GmM7W22pu4yP JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWE_RsaOaepAesGcm_X509.Decrypt > True : {"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ0eXAiOiJKV1QifQ.QzqiUMQh1bbmG8As9A4s0XXsMUR27oj5IJ8aazVZAWc2yf9F3BfCQaFR8M2Mcwglr9SXTgcBqJSgGItFgXiSt7UEtey06ubImo9gAp9BgcQmQTjsVTBHW5VWLJH23jnOCDl_XmqqE_Aqb992QvpiKdrgnvTg4qlyFymtJxU_xlcfsL8B5JqApiTQBPj96J7ta9vgZQx7tFOh23jGS5kt-7onNWs7NLOPVVM1wtEh4a49JLQl9gLfocMGnV9q_X2CEq-35XIe8dkfX_BsSh50YvMlbRSTCCmiGnumsMF77v_22WakHtFqsgEiNq7ZWXhaSKPLe-rVXaikkzUbtn8Mnw.p5ht61WtDaG_z9si.Hr2vtD16A9_rQDBn1F8kMp2OCsByvZXxF_4GAOvFugkwTnbOi1h_AJdtjg.3zK5dgHR3hZB4l5I2tTmFg +JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ0eXAiOiJKV1QifQ.IwnpxrUfsNSckFqwLbuUS-ZydRHPTtUTpyxzSO4_tze30BFwxQE_h6gZqONO4_cLRI3ME_P7B3HziCplPzq5ET_LqyK53uviKYwC9tHNRj-cV0SDOCp6jIeVp4-O4NFsTxkyCOnQNjL4uvPB_jHs3nETtHkL-QqZsVTYKvYt0FZB7rdQf0APZx5E-9G_9KQUjY19EOvNOkyfobAU21m19og3RF2ENoLFgcpoA4ewriJ9_e4-vx82Va5IHytKbYcy0dMRalqtELlQgw5YuHPWDInIdXzEUJgD1GSOrWQrOaaq_kdKSL0Q464cs6DjI32AWcQZRetq1DkFM0xw62d0vg.OdGwvvySDZ0hZK2J.UhsKUfYEEVU4qUulSx-_t6Qq3qHjeyv5_-_ZvJ-ABNQqZBH8w4ZIE_X1UA.pvAXDmh2vzHaYoE29C_4Uw JweAlgorithm.xLibTest > JWE Header: {"alg":"RSA-OAEP","enc":"A256GCM","typ":"JWT"} -JweAlgorithm.xLibTest > JWE Encrypted Key: QzqiUMQh1bbmG8As9A4s0XXsMUR27oj5IJ8aazVZAWc2yf9F3BfCQaFR8M2Mcwglr9SXTgcBqJSgGItFgXiSt7UEtey06ubImo9gAp9BgcQmQTjsVTBHW5VWLJH23jnOCDl_XmqqE_Aqb992QvpiKdrgnvTg4qlyFymtJxU_xlcfsL8B5JqApiTQBPj96J7ta9vgZQx7tFOh23jGS5kt-7onNWs7NLOPVVM1wtEh4a49JLQl9gLfocMGnV9q_X2CEq-35XIe8dkfX_BsSh50YvMlbRSTCCmiGnumsMF77v_22WakHtFqsgEiNq7ZWXhaSKPLe-rVXaikkzUbtn8Mnw -JweAlgorithm.xLibTest > JWE Initialization Vector: p5ht61WtDaG_z9si -JweAlgorithm.xLibTest > JWE Ciphertext: Hr2vtD16A9_rQDBn1F8kMp2OCsByvZXxF_4GAOvFugkwTnbOi1h_AJdtjg -JweAlgorithm.xLibTest > JWE Authentication Tag: 3zK5dgHR3hZB4l5I2tTmFg +JweAlgorithm.xLibTest > JWE Encrypted Key: IwnpxrUfsNSckFqwLbuUS-ZydRHPTtUTpyxzSO4_tze30BFwxQE_h6gZqONO4_cLRI3ME_P7B3HziCplPzq5ET_LqyK53uviKYwC9tHNRj-cV0SDOCp6jIeVp4-O4NFsTxkyCOnQNjL4uvPB_jHs3nETtHkL-QqZsVTYKvYt0FZB7rdQf0APZx5E-9G_9KQUjY19EOvNOkyfobAU21m19og3RF2ENoLFgcpoA4ewriJ9_e4-vx82Va5IHytKbYcy0dMRalqtELlQgw5YuHPWDInIdXzEUJgD1GSOrWQrOaaq_kdKSL0Q464cs6DjI32AWcQZRetq1DkFM0xw62d0vg +JweAlgorithm.xLibTest > JWE Initialization Vector: OdGwvvySDZ0hZK2J +JweAlgorithm.xLibTest > JWE Ciphertext: UhsKUfYEEVU4qUulSx-_t6Qq3qHjeyv5_-_ZvJ-ABNQqZBH8w4ZIE_X1UA +JweAlgorithm.xLibTest > JWE Authentication Tag: pvAXDmh2vzHaYoE29C_4Uw JweAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWE_Rsa15A128CbcHS256_X509.Decrypt > True : {"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidHlwIjoiSldUIn0.AbOg32Wq4VUypLhrYFe9ibRCUFV89I0mlK5W8U9kTiyifX6OGuYqhSDYzSlznhva3TWkiq4nYrKU-7Ke9JV3sQu_02r5YP1kymko7h-511AOWg7cSgfMLCMbMZNBSwi5DMZq4YZSvSCtdEyLR0qGTolPJ5B1mzrBuSqrGHR7YIJfdD7ppDyt6Ovb1zgMJ-9q3eQ-GTYcsz9sM8oe7V8_g3YgzpslUQRYoUS8n_Clrv4lJQvNxQkJBoAUU_u2OLkV77LpiThnYCGxyYIlzEHchMZyVH0NMf6A_GwEljo_hl0xt_nLPZjcargsA0GOkVnudsMDsvmArND2fvGhgihyVg.1cv_E7mfMc3aDY_c62IorQ.zwZqEErqyU4ykynxzXTkv_12UW4C7A4lP-PWV9DhPxr655vhi8jVEemLMMkpyxFf.zaQQjMyTDimHUC0aEcDLcA +JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidHlwIjoiSldUIn0.AN6yuMxlYrFH1-qHnaMnXOxHHsu2uXT1t1eWfL0qpYQJIoWo7uIRQfS8Yw7EzTmeQ8TaHzE3KktkqMZEVW1bFheaHCFSLvAcs0XT6vNxE3-gfibttHMWEaOKbNNkaOLOJYiQskSx8AEdDcvc7ZxP-kW7G9jeGHAQ9rsalS4FUjTfDDLLEC10bKajmsO3-dFgUr_nEfe6OSA44Mbq2KtneFt01fzZ5lqUTWSCQeQt0zJFGDXB4_DR9H7Xia-40HDdTPflUC0iPCwovKLMGnbiolffDCuCYbm_X_fMuYoibKG6eQ7uM7zcTcxaXUIYHzGjiZrmSbNsdlQreaMBUnlxzQ.bLwREMiElrBYnz27P7OrjQ.KAVemierHAnpysl2R6VUgqV35JauJJFnB_tPolKqWZpHzfHjLukjbpMjBhemX2um.DfW7JjpqYopkZQk7iWSYGQ JweAlgorithm.xLibTest > JWE Header: {"alg":"RSA1_5","enc":"A128CBC-HS256","typ":"JWT"} -JweAlgorithm.xLibTest > JWE Encrypted Key: AbOg32Wq4VUypLhrYFe9ibRCUFV89I0mlK5W8U9kTiyifX6OGuYqhSDYzSlznhva3TWkiq4nYrKU-7Ke9JV3sQu_02r5YP1kymko7h-511AOWg7cSgfMLCMbMZNBSwi5DMZq4YZSvSCtdEyLR0qGTolPJ5B1mzrBuSqrGHR7YIJfdD7ppDyt6Ovb1zgMJ-9q3eQ-GTYcsz9sM8oe7V8_g3YgzpslUQRYoUS8n_Clrv4lJQvNxQkJBoAUU_u2OLkV77LpiThnYCGxyYIlzEHchMZyVH0NMf6A_GwEljo_hl0xt_nLPZjcargsA0GOkVnudsMDsvmArND2fvGhgihyVg -JweAlgorithm.xLibTest > JWE Initialization Vector: 1cv_E7mfMc3aDY_c62IorQ -JweAlgorithm.xLibTest > JWE Ciphertext: zwZqEErqyU4ykynxzXTkv_12UW4C7A4lP-PWV9DhPxr655vhi8jVEemLMMkpyxFf -JweAlgorithm.xLibTest > JWE Authentication Tag: zaQQjMyTDimHUC0aEcDLcA +JweAlgorithm.xLibTest > JWE Encrypted Key: AN6yuMxlYrFH1-qHnaMnXOxHHsu2uXT1t1eWfL0qpYQJIoWo7uIRQfS8Yw7EzTmeQ8TaHzE3KktkqMZEVW1bFheaHCFSLvAcs0XT6vNxE3-gfibttHMWEaOKbNNkaOLOJYiQskSx8AEdDcvc7ZxP-kW7G9jeGHAQ9rsalS4FUjTfDDLLEC10bKajmsO3-dFgUr_nEfe6OSA44Mbq2KtneFt01fzZ5lqUTWSCQeQt0zJFGDXB4_DR9H7Xia-40HDdTPflUC0iPCwovKLMGnbiolffDCuCYbm_X_fMuYoibKG6eQ7uM7zcTcxaXUIYHzGjiZrmSbNsdlQreaMBUnlxzQ +JweAlgorithm.xLibTest > JWE Initialization Vector: bLwREMiElrBYnz27P7OrjQ +JweAlgorithm.xLibTest > JWE Ciphertext: KAVemierHAnpysl2R6VUgqV35JauJJFnB_tPolKqWZpHzfHjLukjbpMjBhemX2um +JweAlgorithm.xLibTest > JWE Authentication Tag: DfW7JjpqYopkZQk7iWSYGQ JweAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JwsAlgorithm.none > eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ. JwsAlgorithm.HS256 > Original:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.dvd5Ak6zcBy0OB7gxVtehT3Ab5NO7XEggon6r_CTSfE @@ -149,75 +149,75 @@ JwsAlgorithm.HS256 > JWS Header: {"alg":"HS256","typ":"JWT"} JwsAlgorithm.HS256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} JwsAlgorithm.HS256 > JWS Signature: dvd5Ak6zcBy0OB7gxVtehT3Ab5NO7XEggon6r_CTSfE JwsAlgorithm.HS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.RS256 > Original:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.dCnfv92uWPC6q3quXU_a_fYPjZQreuNQIpFx5Qc1k61F_sQch8aNafx_SOP5vIm_eSaqKQSpg7f4BukGAvDMCBTTRANJvj4olE7nhEgzD3jmuvEcrovcM6c3Q6C7oTdNVCDZSRvluiI7rKLgFuLq1iQfTJdX_jPxOIkyO7VR8kA +JwsAlgorithm.RS256 > Original:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.LryZfTY1giiop3yDMDDBBJmMLw6mmyGJR1bHia6VR-riiQU3Gb_0-rEq13Qnis2FWcqixPDRUtMRRXOHVPb2nC6oApqXzTYa8ncRIeiACVBujvgo9X5jMrGCLURjzADQQAz6Sv6GMDfYXzmsoQ-yOX8FI9CfEi1UAqKKunG1FuY JwsAlgorithm.RS256 > JWS Header: {"alg":"RS256","typ":"JWT"} JwsAlgorithm.RS256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.RS256 > JWS Signature: dCnfv92uWPC6q3quXU_a_fYPjZQreuNQIpFx5Qc1k61F_sQch8aNafx_SOP5vIm_eSaqKQSpg7f4BukGAvDMCBTTRANJvj4olE7nhEgzD3jmuvEcrovcM6c3Q6C7oTdNVCDZSRvluiI7rKLgFuLq1iQfTJdX_jPxOIkyO7VR8kA +JwsAlgorithm.RS256 > JWS Signature: LryZfTY1giiop3yDMDDBBJmMLw6mmyGJR1bHia6VR-riiQU3Gb_0-rEq13Qnis2FWcqixPDRUtMRRXOHVPb2nC6oApqXzTYa8ncRIeiACVBujvgo9X5jMrGCLURjzADQQAz6Sv6GMDfYXzmsoQ-yOX8FI9CfEi1UAqKKunG1FuY JwsAlgorithm.RS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.5sjTJ18OthXG2r7iWeuwX5F63oyMTYmHYEhTWaDnsZNbiImVfoMsv9m4ovocZmzeJRIuHnxokyEd1sHBtrSAog +JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.EN7A3AvwOSCItxxpf3wQzmhB98biQ_xn3e9T0k6A8PLC8wLl_ml7rRtVQ0pfEndPmKneFVPyARCgLQ2YqBMklg JwsAlgorithm.ES256 > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.ES256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > JWS Signature: 5sjTJ18OthXG2r7iWeuwX5F63oyMTYmHYEhTWaDnsZNbiImVfoMsv9m4ovocZmzeJRIuHnxokyEd1sHBtrSAog +JwsAlgorithm.ES256 > JWS Signature: EN7A3AvwOSCItxxpf3wQzmhB98biQ_xn3e9T0k6A8PLC8wLl_ml7rRtVQ0pfEndPmKneFVPyARCgLQ2YqBMklg JwsAlgorithm.ES256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.y9GTdsHGsPJwZbBXI54d1J-AFfpRmcxIEeJ7KqlyPyehkGS0p3h9OIyXJL67Nykg1IFPFkkk6cSI6aEpzRf36g +JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.L08LC-GVKHKXtsTNb2i0mM_NJLU6yiHIuGDX30sXBDwuvC0UU3DBomdHw5sp5K8m3woEJ3YB47BXF34os3BoBA JwsAlgorithm.ES256 > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.ES256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > JWS Signature: y9GTdsHGsPJwZbBXI54d1J-AFfpRmcxIEeJ7KqlyPyehkGS0p3h9OIyXJL67Nykg1IFPFkkk6cSI6aEpzRf36g +JwsAlgorithm.ES256 > JWS Signature: L08LC-GVKHKXtsTNb2i0mM_NJLU6yiHIuGDX30sXBDwuvC0UU3DBomdHw5sp5K8m3woEJ3YB47BXF34os3BoBA JwsAlgorithm.ES256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.Y-Z-EuZU8migC37s312S2qyiLYHuT3e5SD4aswf9FKGtQ35V2OcsY4DqS1TRk8RF5e_YjHMAbXNz8heBNYmspx9PU8tJvAVfWrJhRvvt_SO0jpv7YD-HweQLAGMbE2WWGFrSFDWIJO2Hbijy4xKXqy920U1OrfK02rW-sOtNAXoCGrSV3WQd5eEUV4Z0gF16V3RiO33xtc6Gqy8kmSHSVdC7ThhUVhxGygbAZBbGdnq45iWj-SLD3l143nthn_6I51DKxuzrxTI8rnRFqgCiyrFXRYDJ4haLdg9vkMUg65WjE9OpUo2CD5TqzeW01K2_l5gvo3i_rV54TWWi0wld7Q.O6p_BYf5ETk6OXMPzLArpw.IxCHmLYKCg9DWcXIVJyzAYQ31efTIeDRH00NcDwdzgDqhE80zcIYm6t2TH88ers1.TtaEl82V_-cfXnI2fPPd2w +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.Jx87H35BJoRabDGGSGvMjdPOSDhP2Qqm6XdXuznzQtYSDyy6b6diD0NGZw0x2uwC0t806Ff6pBMI-0sU5AH7SORugUEHmaI5_OwONZOo_pJapIlnROABoY9amyP8WXakuPT7K2KMALuAjlQCe-Yo7mIOvhVzWq0nSA4kE37mtlcNWhk53-RVP1f0qtlJMSvMCoY-WWfnQgR7tOMu1XFJ6EGkpDi9KBkwKpXdSZOl4pdx08bJsdRUsaRuJkZP4PxBmMWjDmDuxcNC8tFl_oATyCqy4FUSJDkcicxyrKOElInQuVEvpQTvsNpPw8PTLIKUTqZNeDgzxezDyPROnifZog.OntG6IwWYmqwuwiDTuXsxg.CSe7Hhv9YxcnZyiqDKQUrB4RDtIQAUK8JIQZtuiR1m0vNlbjrcvg4kONRppUWE_6.8lz33XTt79ys1dFafcj6og JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Header: {"alg":"RSA1_5","enc":"A128CBC-HS256"} -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: Y-Z-EuZU8migC37s312S2qyiLYHuT3e5SD4aswf9FKGtQ35V2OcsY4DqS1TRk8RF5e_YjHMAbXNz8heBNYmspx9PU8tJvAVfWrJhRvvt_SO0jpv7YD-HweQLAGMbE2WWGFrSFDWIJO2Hbijy4xKXqy920U1OrfK02rW-sOtNAXoCGrSV3WQd5eEUV4Z0gF16V3RiO33xtc6Gqy8kmSHSVdC7ThhUVhxGygbAZBbGdnq45iWj-SLD3l143nthn_6I51DKxuzrxTI8rnRFqgCiyrFXRYDJ4haLdg9vkMUg65WjE9OpUo2CD5TqzeW01K2_l5gvo3i_rV54TWWi0wld7Q -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: O6p_BYf5ETk6OXMPzLArpw -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Ciphertext: IxCHmLYKCg9DWcXIVJyzAYQ31efTIeDRH00NcDwdzgDqhE80zcIYm6t2TH88ers1 -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: TtaEl82V_-cfXnI2fPPd2w +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: Jx87H35BJoRabDGGSGvMjdPOSDhP2Qqm6XdXuznzQtYSDyy6b6diD0NGZw0x2uwC0t806Ff6pBMI-0sU5AH7SORugUEHmaI5_OwONZOo_pJapIlnROABoY9amyP8WXakuPT7K2KMALuAjlQCe-Yo7mIOvhVzWq0nSA4kE37mtlcNWhk53-RVP1f0qtlJMSvMCoY-WWfnQgR7tOMu1XFJ6EGkpDi9KBkwKpXdSZOl4pdx08bJsdRUsaRuJkZP4PxBmMWjDmDuxcNC8tFl_oATyCqy4FUSJDkcicxyrKOElInQuVEvpQTvsNpPw8PTLIKUTqZNeDgzxezDyPROnifZog +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: OntG6IwWYmqwuwiDTuXsxg +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Ciphertext: CSe7Hhv9YxcnZyiqDKQUrB4RDtIQAUK8JIQZtuiR1m0vNlbjrcvg4kONRppUWE_6 +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: 8lz33XTt79ys1dFafcj6og JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.IOfHVVGvdIJiMfsRG6L28LVOD0t14-EXFEFLYZrGJiXoRHwoYVnP1IcQOK5Wx28V7AzkZ7zNnKEymrMPedt5nsORo4ctv8LsHX1zS_xFGfB4OB1EfSj5LUaZ0JkKcEyH0aJ7gcyv578hci1gVu-zloTRUb56IgLUUiCi0MkjXVAYocY2wgDeFtiLdgaTP_aIpVEwCOrCjQWDrguyhQzI52O9sa0W7HjV34iAAWFf1eLqx0klp48NOvegHh0hTu1850t3PE9FsCzfNqFclsWHjzRpCzxE2IZCUzXxaHNd79KlaXRhzphJ5OocCvOF7me1GGMEz7XwZRAjft_GPDeEDg.akAAMGRTkDsjmr7x.kOOA9YbIk8oUIe_Yp4EnwSjo-bQm_aVaWO1LNwwzDQexvmmPrIjJOzX-tQ.AzhMl3Kmr_eoiNrZjelA3w +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.AeMV-GPV8HRaouDUK4FnPK66xefUPgewKMbeDmXT6jaluCR0UO_aArOC0Gw0QAfJFQmBcbbdafXea7C0DLkY2vesNdzwba3HX1mqCYeEUvy2jkzJZIp111F6ocAgQ9agpjLh8YKruvi-7h_FLFIJhprff9Jk_rxb9fzYAoBkeNAox1mFdE2s3XaH2vLXoGsFB2619u9bdL1-iFApDWMdHH3TeK0LPudYF-119dF-1QBbkXIZ7TmkcfZtzWMOdj-G4a79mwGfqb5Q3qwhi-0lVE1SPrZd5G5-XnRD5-d5jFThTtF4SRIAvvoRopmIAevheEWzTMz67D88Pnf9QyxUgQ.uhpGtLB0Hpc-2Y9n.ZNpHoDOdF2ghM0gNilhC9GsVIkEG1yw-Zj1HYBwQPVUiGnmOZNZzas0DEA.FY-nlEToGu3PCge8P-TtJA JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Header: {"alg":"RSA-OAEP","enc":"A256GCM"} -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Encrypted Key: IOfHVVGvdIJiMfsRG6L28LVOD0t14-EXFEFLYZrGJiXoRHwoYVnP1IcQOK5Wx28V7AzkZ7zNnKEymrMPedt5nsORo4ctv8LsHX1zS_xFGfB4OB1EfSj5LUaZ0JkKcEyH0aJ7gcyv578hci1gVu-zloTRUb56IgLUUiCi0MkjXVAYocY2wgDeFtiLdgaTP_aIpVEwCOrCjQWDrguyhQzI52O9sa0W7HjV34iAAWFf1eLqx0klp48NOvegHh0hTu1850t3PE9FsCzfNqFclsWHjzRpCzxE2IZCUzXxaHNd79KlaXRhzphJ5OocCvOF7me1GGMEz7XwZRAjft_GPDeEDg -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Initialization Vector: akAAMGRTkDsjmr7x -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Ciphertext: kOOA9YbIk8oUIe_Yp4EnwSjo-bQm_aVaWO1LNwwzDQexvmmPrIjJOzX-tQ -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Authentication Tag: AzhMl3Kmr_eoiNrZjelA3w +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Encrypted Key: AeMV-GPV8HRaouDUK4FnPK66xefUPgewKMbeDmXT6jaluCR0UO_aArOC0Gw0QAfJFQmBcbbdafXea7C0DLkY2vesNdzwba3HX1mqCYeEUvy2jkzJZIp111F6ocAgQ9agpjLh8YKruvi-7h_FLFIJhprff9Jk_rxb9fzYAoBkeNAox1mFdE2s3XaH2vLXoGsFB2619u9bdL1-iFApDWMdHH3TeK0LPudYF-119dF-1QBbkXIZ7TmkcfZtzWMOdj-G4a79mwGfqb5Q3qwhi-0lVE1SPrZd5G5-XnRD5-d5jFThTtF4SRIAvvoRopmIAevheEWzTMz67D88Pnf9QyxUgQ +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Initialization Vector: uhpGtLB0Hpc-2Y9n +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Ciphertext: ZNpHoDOdF2ghM0gNilhC9GsVIkEG1yw-Zj1HYBwQPVUiGnmOZNZzas0DEA +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Authentication Tag: FY-nlEToGu3PCge8P-TtJA JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..gcGPcw6lYQ4-nUCB-I-Q-A.XROkpOO8PEr3IPKGnRWLp3sur6B3SqSogYb_TiUKi1sJuz1KgCIRoGZnZvHH9xCg.GbbV94uHu6Juz9GSW3-2ug +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..jLhaMhFAYAY19uuDGVxTDg.nUhSmzBtsxeceMqU0G2JtmAfLFiMyQNLAReLVRq8YIUiBP-XLWR4lo0B-UtytxSw.bnf9BN5zKhTYAVSfgYT8zQ JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Header: {"alg":"dir","enc":"A128CBC-HS256"} JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: gcGPcw6lYQ4-nUCB-I-Q-A -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Ciphertext: XROkpOO8PEr3IPKGnRWLp3sur6B3SqSogYb_TiUKi1sJuz1KgCIRoGZnZvHH9xCg -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: GbbV94uHu6Juz9GSW3-2ug +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: jLhaMhFAYAY19uuDGVxTDg +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Ciphertext: nUhSmzBtsxeceMqU0G2JtmAfLFiMyQNLAReLVRq8YIUiBP-XLWR4lo0B-UtytxSw +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: bnf9BN5zKhTYAVSfgYT8zQ JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.nvzrNLij1eLkzWX9OvZv3lYCcKgxUjP5cqTUdq6SAT5jmB4Y6pdQ-1Gb_6NGJTf6k_AyjQca7cYHlijToocnekneR7dpibAS.wC0BKrRqaaure-mQP8DWuQ.QPL69JM4Nw6_iNlRJu63J8_eiHOVhAB591n2lewNZZlrmTjMeITdU69vuzlZebKZ.nxhdVnuH8G6ZtlPVIvQui2TxOvfuClY3A-sfZjs8aeo +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.1Um0QQ-pxW1qxTNHoo8hdNtbqCl1YkphtsL7cyEts8KZtxN0_seXi0_2cK497Ss6hbdVXB31YS6MoBBChEpSpllXKZV_XJV1.5rPrLd3OxNU1eagQfD5WNA.VTQd1YwVxGWC_upXT-7u0o-tOIDt5_JmbG3852BVVw1PZ5cjB088-16DbyDHhMWx.GEk3p131oAA8cDMlFJpbonDlcUv2H-O8QHQ16lVcf6Y JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256KW","enc":"A256CBC-HS512"} -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: nvzrNLij1eLkzWX9OvZv3lYCcKgxUjP5cqTUdq6SAT5jmB4Y6pdQ-1Gb_6NGJTf6k_AyjQca7cYHlijToocnekneR7dpibAS -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: wC0BKrRqaaure-mQP8DWuQ -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: QPL69JM4Nw6_iNlRJu63J8_eiHOVhAB591n2lewNZZlrmTjMeITdU69vuzlZebKZ -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: nxhdVnuH8G6ZtlPVIvQui2TxOvfuClY3A-sfZjs8aeo +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: 1Um0QQ-pxW1qxTNHoo8hdNtbqCl1YkphtsL7cyEts8KZtxN0_seXi0_2cK497Ss6hbdVXB31YS6MoBBChEpSpllXKZV_XJV1 +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: 5rPrLd3OxNU1eagQfD5WNA +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: VTQd1YwVxGWC_upXT-7u0o-tOIDt5_JmbG3852BVVw1PZ5cjB088-16DbyDHhMWx +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: GEk3p131oAA8cDMlFJpbonDlcUv2H-O8QHQ16lVcf6Y JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2R0NNS1ciLCJpdiI6IlcwbHQ1T1B0YzB5cHVybzYiLCJ0YWciOiJvMUd0VXR1YjhQTHBKb2I5ekdYVUtnIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiJ9.UiTUcWTyHjkxA2khlzfJcEc62t-EHA8QpjeZu_K2xgeSbSSpNWJH9X_XsHYUU1W2aMG9cSMmw77ULxUWZLOUTg.jKUCAdU3VQ9GNECTVL27ug.FkbDex80HqKcsQ-M-HnJsL3VZSq49CkCHrL77VGTlTed7m135Jiy4kHsdgbbQqYL.rcQUTu0zg2oToqtZIS7oKvSlz94gfOaonwbDmNYwrRA -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256GCMKW","iv":"W0lt5OPtc0ypuro6","tag":"o1GtUtub8PLpJob9zGXUKg","enc":"A256CBC-HS512"} -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: UiTUcWTyHjkxA2khlzfJcEc62t-EHA8QpjeZu_K2xgeSbSSpNWJH9X_XsHYUU1W2aMG9cSMmw77ULxUWZLOUTg -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: jKUCAdU3VQ9GNECTVL27ug -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: FkbDex80HqKcsQ-M-HnJsL3VZSq49CkCHrL77VGTlTed7m135Jiy4kHsdgbbQqYL -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: rcQUTu0zg2oToqtZIS7oKvSlz94gfOaonwbDmNYwrRA +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2R0NNS1ciLCJpdiI6ImlDLTZMQkdQRlcyZ2xPTXYiLCJ0YWciOiItb3VyVE1BaXlMdHhYeVhIWFNFVHZBIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiJ9.8Nm8p4Gi50zcqKE7zTjnv_KstRSunJ3SqSIE-6lEgEUwh5W-y0PhqWqa90HBEhYcv0cgU4mMx3yRNPWiR2yDsQ.wrch6_pCQ4f-WYVcsXVoVA.zMoZdjPWG9GaJ0a4jicx0eDH7fN7ZWmiQ7AqwV6WAMUdqZcG04EcygEdkwl5pFJ6.tQW0Ltoy0ipGsCyrqbk7cc05c-xa1aP94HJzJtPK9mc +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256GCMKW","iv":"iC-6LBGPFW2glOMv","tag":"-ourTMAiyLtxXyXHXSETvA","enc":"A256CBC-HS512"} +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: 8Nm8p4Gi50zcqKE7zTjnv_KstRSunJ3SqSIE-6lEgEUwh5W-y0PhqWqa90HBEhYcv0cgU4mMx3yRNPWiR2yDsQ +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: wrch6_pCQ4f-WYVcsXVoVA +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: zMoZdjPWG9GaJ0a4jicx0eDH7fN7ZWmiQ7AqwV6WAMUdqZcG04EcygEdkwl5pFJ6 +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: tQW0Ltoy0ipGsCyrqbk7cc05c-xa1aP94HJzJtPK9mc JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > Original:eyJhbGciOiJFQ0RILUVTIiwiZXBrIjp7Imt0eSI6IkVDIiwieCI6IlhEMmJkSDFONmtBRVJURE9pZ3J6M1dwVWdHVUxLTzNMdXJ3QVpnWHoxZ28iLCJ5IjoiREtpdFM5eFQ5Vy1vUW1GUE1OcmgySGlXbDV5Q3NGREdEQWJpaDBBLVdiTSIsImNydiI6IlAtMjU2In0sImVuYyI6IkEyNTZHQ00ifQ..4_YxIEHgT0S3THYo.fgzS9zycj3N3Ts4BNN5kIduq0dxmc-p7FPsxQRsLoPly7bxBjbRZWyMinw.pSS_005rtwkI8zS2ci4RcQ -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Header: {"alg":"ECDH-ES","epk":{"kty":"EC","x":"XD2bdH1N6kAERTDOigrz3WpUgGULKO3LurwAZgXz1go","y":"DKitS9xT9W-oQmFPMNrh2HiWl5yCsFDGDAbih0A-WbM","crv":"P-256"},"enc":"A256GCM"} +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > Original:eyJhbGciOiJFQ0RILUVTIiwiZXBrIjp7Imt0eSI6IkVDIiwieCI6IlV4Z0tGQnQ5Ni1zcVh6OVVjUjJCVVYxTlI5QjVsZWJKdDJSZW02WFlFbUUiLCJ5IjoiRWlrVVp4bWRuaVZNUHNBQkhNZlJpRUJNakFpZERhMFBPdEJhYThvYWJZYyIsImNydiI6IlAtMjU2In0sImVuYyI6IkEyNTZHQ00ifQ..IDyazcSRfoVWdvOF.lLkxpkR7U9mUDf8hFpAT5ujoGIS-Q1alkNmZcCNzrXngX8b0HFr7Djgp-g.vxnfi9esHyMqD-QhXtcHog +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Header: {"alg":"ECDH-ES","epk":{"kty":"EC","x":"UxgKFBt96-sqXz9UcR2BUV1NR9B5lebJt2Rem6XYEmE","y":"EikUZxmdniVMPsABHMfRiEBMjAidDa0POtBaa8oabYc","crv":"P-256"},"enc":"A256GCM"} JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Encrypted Key: -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Initialization Vector: 4_YxIEHgT0S3THYo -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Ciphertext: fgzS9zycj3N3Ts4BNN5kIduq0dxmc-p7FPsxQRsLoPly7bxBjbRZWyMinw -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Authentication Tag: pSS_005rtwkI8zS2ci4RcQ +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Initialization Vector: IDyazcSRfoVWdvOF +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Ciphertext: lLkxpkR7U9mUDf8hFpAT5ujoGIS-Q1alkNmZcCNzrXngX8b0HFr7Djgp-g +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Authentication Tag: vxnfi9esHyMqD-QhXtcHog JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > System.Security.Cryptography.CryptographicException, キーがありません。 -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJwMmMiOjgxOTIsInAycyI6IjhoZVFTUXhHUTFsekZMOGkiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.4w8H_QQeqtndy2gxSZoPQXYkErH5ynn9XblJCOoiSSCzBL9o2PmrbWHGOxS7ot0WA5YXlFzqLP6RPe27JwbsFW_dNG4rZTjE.SkrHmQA8V4vV-O6QppWSzg.Oj4F5E9wx7wFLTs-zq45PQNfqVjK4H2D4fRs0AiGyRnzSfquNau49hpKg6fERiNJ.MkcoNWK1OgXT0BsrJ83HhhoTTno_1RdHqHtl1-BfyMM -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"PBES2-HS256+A128KW","p2c":8192,"p2s":"8heQSQxGQ1lzFL8i","enc":"A256CBC-HS512"} -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: 4w8H_QQeqtndy2gxSZoPQXYkErH5ynn9XblJCOoiSSCzBL9o2PmrbWHGOxS7ot0WA5YXlFzqLP6RPe27JwbsFW_dNG4rZTjE -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: SkrHmQA8V4vV-O6QppWSzg -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: Oj4F5E9wx7wFLTs-zq45PQNfqVjK4H2D4fRs0AiGyRnzSfquNau49hpKg6fERiNJ -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: MkcoNWK1OgXT0BsrJ83HhhoTTno_1RdHqHtl1-BfyMM +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJwMmMiOjgxOTIsInAycyI6IjNzN19uTmZKeXYtbURpNXgiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.ODgcjLwujHdAA725X4472mlS26WnJmw9Ql2eloHuhpdCQEFJBE2Zw0jOj1-NsyLEsmjahAT-F8cT3Z4SFul_svem6ZQ-OuYv.UIRgdq6HmfKYKOAqeV8vbA.bRm0ZYt2qPH9zyLQHgg4giQuQ1giD6noYjdpkpi7sCnaz6npcdGf9-3DwaNSbv_1.1PJcXqJPaZeKcnOWqkmu0sPyFEDofKhLbNbbMiFyC_U +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"PBES2-HS256+A128KW","p2c":8192,"p2s":"3s7_nNfJyv-mDi5x","enc":"A256CBC-HS512"} +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: ODgcjLwujHdAA725X4472mlS26WnJmw9Ql2eloHuhpdCQEFJBE2Zw0jOj1-NsyLEsmjahAT-F8cT3Z4SFul_svem6ZQ-OuYv +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: UIRgdq6HmfKYKOAqeV8vbA +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: bRm0ZYt2qPH9zyLQHgg4giQuQ1giD6noYjdpkpi7sCnaz6npcdGf9-3DwaNSbv_1 +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: 1PJcXqJPaZeKcnOWqkmu0sPyFEDofKhLbNbbMiFyC_U JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -Adding extra headers to RS256 > Original:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCIsImtleWlkIjoiMTExLTIyMi0zMzMifQ.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.FSr9pqYSF8WxBNdahQ30fFnmATRtUIvuNPn8Vzeb7tncuC-m3AiEqqP02hTskzYWb5yL65Ms8WUSPUpPuq3fpOAEPaMQlB_tD1Cm9VdUWVVb2QenpYErlwghhieiaRwhNxb_HtgMEVSaUGl19rbuVSQrFZbK4xF2vcl1Mf0AIcQ +Adding extra headers to RS256 > Original:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCIsImtleWlkIjoiMTExLTIyMi0zMzMifQ.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.YjUoaYEVowCWxm3SMc-hoFDP0_iWqrat14hEXTGS1XZWdpuchtXI9IiDpi5r2mx8hbI4ySRXSEzxAVMgPyj2l0wOVozsSM0moVacp9rVC7Jkre2GtJ1pciA5rO03TX6ylkNSOQ5ggOrm368dg8kOf52FA5u_eLCAqMSjg9l0SDQ Adding extra headers to RS256 > JWS Header: {"alg":"RS256","typ":"JWT","cty":"JWT","keyid":"111-222-333"} Adding extra headers to RS256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -Adding extra headers to RS256 > JWS Signature: FSr9pqYSF8WxBNdahQ30fFnmATRtUIvuNPn8Vzeb7tncuC-m3AiEqqP02hTskzYWb5yL65Ms8WUSPUpPuq3fpOAEPaMQlB_tD1Cm9VdUWVVb2QenpYErlwghhieiaRwhNxb_HtgMEVSaUGl19rbuVSQrFZbK4xF2vcl1Mf0AIcQ +Adding extra headers to RS256 > JWS Signature: YjUoaYEVowCWxm3SMc-hoFDP0_iWqrat14hEXTGS1XZWdpuchtXI9IiDpi5r2mx8hbI4ySRXSEzxAVMgPyj2l0wOVozsSM0moVacp9rVC7Jkre2GtJ1pciA5rO03TX6ylkNSOQ5ggOrm368dg8kOf52FA5u_eLCAqMSjg9l0SDQ Adding extra headers to RS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} Strict validation(RS256) > {"sub":"mr.x@contoso.com","exp":1300819380} -Verify nested signedXml > True : <?xml version="1.0" encoding="utf-8"?><xml><a ID="a"><b ID="b"><c /><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#b"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>+sg4j+LFYSzu6ZSzp2Jrh7CxLATJlNH/KTEQlXcfmtM=</DigestValue></Reference></SignedInfo><SignatureValue>FBB/YzsLszo0rDe8Mvb1s8JbHxNm59IEVdU8q+rkKa13lsXuSiuSDq/Cw3C3RW3VFy5nJJiOVbCQ6FwHSGhY4vSa3fgohWIPDYKFDTzToxuqrX2W5wsjnl26DiHpBCkWjpGJqEWD6VH9yLWBgo+5ltRLVJRLMoGPj+9/EmjFY/4=</SignatureValue></Signature></b><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#a"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>puYEL9d9TeBL7MbOia9vcx3qOeyBRiciAwi4MxsjAoI=</DigestValue></Reference></SignedInfo><SignatureValue>sbNtaEdIQUxdzJG+ihGnJD9+03JjcKhcG1rRdL2dNA0FhUmSY3D0yT58UNTDOWZ1482op1ixGqLcMhtFs1+PyxoQsA0++YndIf8biE5L+gzktyx6j4d3LtbxujHtT3+HxcEvOOjOXsk2jaTngCJMTrX0Ig3PaF39l/RSok6xVME=</SignatureValue></Signature></a></xml> +Verify nested signedXml > True : <?xml version="1.0" encoding="utf-8"?><xml><a ID="a"><b ID="b"><c /><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#b"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>+sg4j+LFYSzu6ZSzp2Jrh7CxLATJlNH/KTEQlXcfmtM=</DigestValue></Reference></SignedInfo><SignatureValue>korSFdb6rQCLsONePfaog1UPMuYI2S9aE6oy/CCnm/nHyR5fXVjRCf79gQNR+VZjGZISv01pSO3SIGcU4hCx2340B2CM2al2KaI8z0g/IXcECMGqIGdowZ1882x5ycdFTf89wzd3yqWqgWwggKBtl042gbAdHGWj62HNcH66RmY=</SignatureValue></Signature></b><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#a"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>EG+LZsGzk/IuARzMrAK5MfMrZiIx5xvICM4wims8XNM=</DigestValue></Reference></SignedInfo><SignatureValue>SbMDlPhnRB9z5DLU/5GzBR3GLcPyyz+xUzPMQ8gicfgbJhN4anOfmx42q8zr5yUjWYcwP3GPrdWUFQV11n61/YBu8SiSsNAuswLPFErXOZKk4XA7oxOIIbL5CBN4RuiQek5jSHfRFK7ozNrBEz/2447SmRnc36iEEVXHU3k+3g0=</SignatureValue></Signature></a></xml> diff --git a/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/ResultCore100.txt b/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/ResultCore100.txt index 48a9fcc70..6c3aadc7f 100644 --- a/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/ResultCore100.txt +++ b/root/programs/CS/Frameworks/Tests/EncAndDecUtilCUI/ResultCore100.txt @@ -77,8 +77,8 @@ JWS_RS256_X509.Verify > True JWS_RS256_Param.Verify > True jWS_RS384_XML.Create > JWS Header: {"alg":"RS384","typ":"JWT"} jWS_RS384_XML.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -jWS_RS384_XML.Create > JWS Signature: shqAjKO-YTBsx6DASpCZW5QtbZWkYC1kYrpZap2eZoNkKVipKekHSnFDoNj3soPMY6hCk5onVOtO9-Ev5_rmJeggEsJ-Vr7JBWRjTc9wRaOmhdXj0wlN_b146TgPTeRTyKeMjeEvp8PiY8hHDKqXHO_b0FeMEwpQU3OBio60AGA -RSA JWK > {"kty":"RSA","alg":"RS384","n":"z0Id6i1UAMLlF8rf5RAtbewG-ncNFFSwK91VXKXqzLPLLK35nxkyQ47zhHXBwtvGcuva3Oe2Nu-xBR33nKrzXPuLb9lvW6T3MnIMU57RyXSKM-nRWWUfgXNrD_r7sa7U5keBjt0l03zVLNRuoPAB9niY2D2N2GH0GMvijRUygq0","e":"AQAB","kid":"dP-zVYRWaQmRfFH2bLdBearWhgmgd3AO4vxdv34FyDN8stXCtz4le8cY1NDYfq7U"} +jWS_RS384_XML.Create > JWS Signature: mTOHvk5zyPdsKZ1nI5_VE5NicVEti2exITuthYpgGVNDpUPhQWV1EA4Se51tWDeBNmjJh_Br0d-9Ah9D3YzOE3YQt14g0ZNzhBJnbQgaCl4VUEOY6xSPUoTH59Pt5mfcL91detkoCZycnYsdGBgAFLZokXrbK3AuV6eEzI_9c-Q +RSA JWK > {"kty":"RSA","alg":"RS384","n":"tGxd_6cdbRPQGEX76gDK1nt5IASA-7h913a8QRWdhQVS3DmJxfg0ExQkBWp0fy3E4LngwUbe6tbVJlHuyU8y2Vf9n4Ao8OJTv7audVPY-aqTo5jlkgZVAcuRFvo8s2WkNRssw-HbGmwzB3XUv-rIbH9oMLmP-jwk6mda8SBa1tU","e":"AQAB","kid":"oAOsvQGPm9VZB0SbAs8O3RrR4PygAlBvr9Lqp1YNM5rM8YePJ9JT60eLW69osNMF"} JWS_RS384_XML.Verify > True JWS_RS384_Param.Verify > True JWS_RS512_X509.Create > JWS Header: {"alg":"RS512","typ":"JWT"} @@ -89,54 +89,54 @@ JWS_RS512_X509.Verify > True JWS_RS512_Param.Verify > True JWS_ES256_X509.Create > JWS Header: {"alg":"ES256","typ":"JWT"} JWS_ES256_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES256_X509.Create > JWS Signature: FdhyZVwp5zW2SDL72d6yIdtJCSPwnfduiyWYL9XvzyFNrLl8pfdDuY2jR6RT41SRvX8ukbowAzSZJrxK0D35RQ +JWS_ES256_X509.Create > JWS Signature: mtGP_hbW-uGRRyDTM6SmHUuYCW2gzKcBK1__GVbmrPN9fgD_t1ghAU4cVeY54ncFYAv0ORiKAb1InCCeGyLwUg ECDSA JWK > {"kty":"EC","alg":"ES256","crv":"P-256","x":"qdS3bsts3UXi5p0G71GofUB9ls1fJz_z0dRQw9RZ99A","y":"hX6HISTIiDLt90VDEqGmsMj2kSlGLOcXgXSqz75EhV4","kid":"asm1SGqVczG7zj0saZPKiggv2xwRlb6c23CDCNBqBNA"} JWS_ES256_X509.Verify > True JWS_ES256_Param.Verify > True -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.FdhyZVwp5zW2SDL72d6yIdtJCSPwnfduiyWYL9XvzyFNrLl8pfdDuY2jR6RT41SRvX8ukbowAzSZJrxK0D35RQ +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.mtGP_hbW-uGRRyDTM6SmHUuYCW2gzKcBK1__GVbmrPN9fgD_t1ghAU4cVeY54ncFYAv0ORiKAb1InCCeGyLwUg JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: FdhyZVwp5zW2SDL72d6yIdtJCSPwnfduiyWYL9XvzyFNrLl8pfdDuY2jR6RT41SRvX8ukbowAzSZJrxK0D35RQ +JwsAlgorithm.xLibTest > JWS Signature: mtGP_hbW-uGRRyDTM6SmHUuYCW2gzKcBK1__GVbmrPN9fgD_t1ghAU4cVeY54ncFYAv0ORiKAb1InCCeGyLwUg JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWS_ES384_X509.Create > JWS Header: {"alg":"ES384","typ":"JWT"} JWS_ES384_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES384_X509.Create > JWS Signature: Y4rg0Z_1ew7Ih3bV1CENag45BWA221TjHAMkY1YSILgWs7e4wnEPq10PnEwIDWOah2sqd_98D1D5KV9tcZ5sMRfZRfuWC7WBvtza9lFrF1A4ZjAzZZ2hJu4WOJWSJqRH +JWS_ES384_X509.Create > JWS Signature: iSmayvO0DaiN0lGTHUoA9zxbIdzMmIvPWKkuD4KSysyq-ciGvX9QgG-rXdpN6cWtEofAZTU2yDe81MYFNct_YbP6-IFV1z4eBXtYvyY-lUezD4Zw2vD77Ie9XRNlXQq5 JWS_ES384_X509.Verify > True ECDSA JWK > {"kty":"EC","alg":"ES384","crv":"P-384","x":"qeyd2iMw8DZT7Yy3KO0mOuok1JBBdMwEuJTa81Upg06fbVbotK8yuhDSVkzSFsw3","y":"thH6faasSDmEO4zeVNdc5LbZJprQmL7JN3NZzYUJmF1GhQEl6QaZh-6f1QhDH0St","kid":"e_kI1ZJ_x9ttzEU_DICgGhJeNK8ghcW3bSl7KFM6eVefpKJHA5ecCowzJw69r9Vr"} JWS_ES384_X509.Verify > True JWS_ES384_Param.Verify > False -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.Y4rg0Z_1ew7Ih3bV1CENag45BWA221TjHAMkY1YSILgWs7e4wnEPq10PnEwIDWOah2sqd_98D1D5KV9tcZ5sMRfZRfuWC7WBvtza9lFrF1A4ZjAzZZ2hJu4WOJWSJqRH +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.iSmayvO0DaiN0lGTHUoA9zxbIdzMmIvPWKkuD4KSysyq-ciGvX9QgG-rXdpN6cWtEofAZTU2yDe81MYFNct_YbP6-IFV1z4eBXtYvyY-lUezD4Zw2vD77Ie9XRNlXQq5 JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES384","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: Y4rg0Z_1ew7Ih3bV1CENag45BWA221TjHAMkY1YSILgWs7e4wnEPq10PnEwIDWOah2sqd_98D1D5KV9tcZ5sMRfZRfuWC7WBvtza9lFrF1A4ZjAzZZ2hJu4WOJWSJqRH +JwsAlgorithm.xLibTest > JWS Signature: iSmayvO0DaiN0lGTHUoA9zxbIdzMmIvPWKkuD4KSysyq-ciGvX9QgG-rXdpN6cWtEofAZTU2yDe81MYFNct_YbP6-IFV1z4eBXtYvyY-lUezD4Zw2vD77Ie9XRNlXQq5 JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWS_ES512_X509.Create > JWS Header: {"alg":"ES512","typ":"JWT"} JWS_ES512_X509.Create > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JWS_ES512_X509.Create > JWS Signature: AZnwnyNqkpF1QoU0Iu2eiEQRMI6O-YMMrJXLe8k26w-1uGEx2tLQZr0DLt2IRfML9SbklhlwDAOAqlXJZLZ0-20RAeIsiyHBOJChGktYKsTvQcEicVofispEUHYtiV7eVYeHF_FY07rkw08h3dqq2vdj0XhchQkbgrTAz5CCSPXyBj8F +JWS_ES512_X509.Create > JWS Signature: AR9jA95xrAcWTWOUCnC0usJyyBxFD1scltNF8edU__UiC_gAC6I60EtToalXZeAwkhpn7OiQpd-W9NeHVi8deRGLAMeCGsYJY3b0L3eepuhXQ9xWQ8eTEtGds8JA0xWW-BuwecuPEPBo9VeCS2vmZBdWDlvhxxF1HXRW7VFyUSlXEhOR JWS_ES512_X509.Verify > True ECDSA JWK > {"kty":"EC","alg":"ES512","crv":"P-521","x":"AQoRdSDzXLfin6CFhLxDOL0_Cfn-QcwgdbMkMGgwTeA4gDIygCOEy4m0eyTmEnjYdBOMN5JtYUiprdZZriAGzrHC","y":"ATj5JBej9ztfsArJLUMCs4edyCgPuItefh7KFGfeefI7YjB-pakcKxzhHZ1h2UhR183bnQ4rrXc71N5WAl3d5BqZ","kid":"OaO51pUD4-aJ8skED2eag0nvd1kfqIwo9BhB86PEZ34PBLE4TiHv6v9LCK20r0c6x06bULLSi84PcldSN2n6DQ"} JWS_ES512_X509.Verify > True JWS_ES512_Param.Verify > False -JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.AZnwnyNqkpF1QoU0Iu2eiEQRMI6O-YMMrJXLe8k26w-1uGEx2tLQZr0DLt2IRfML9SbklhlwDAOAqlXJZLZ0-20RAeIsiyHBOJChGktYKsTvQcEicVofispEUHYtiV7eVYeHF_FY07rkw08h3dqq2vdj0XhchQkbgrTAz5CCSPXyBj8F +JwsAlgorithm.xLibTest > Original:eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.AR9jA95xrAcWTWOUCnC0usJyyBxFD1scltNF8edU__UiC_gAC6I60EtToalXZeAwkhpn7OiQpd-W9NeHVi8deRGLAMeCGsYJY3b0L3eepuhXQ9xWQ8eTEtGds8JA0xWW-BuwecuPEPBo9VeCS2vmZBdWDlvhxxF1HXRW7VFyUSlXEhOR JwsAlgorithm.xLibTest > JWS Header: {"alg":"ES512","typ":"JWT"} JwsAlgorithm.xLibTest > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.xLibTest > JWS Signature: AZnwnyNqkpF1QoU0Iu2eiEQRMI6O-YMMrJXLe8k26w-1uGEx2tLQZr0DLt2IRfML9SbklhlwDAOAqlXJZLZ0-20RAeIsiyHBOJChGktYKsTvQcEicVofispEUHYtiV7eVYeHF_FY07rkw08h3dqq2vdj0XhchQkbgrTAz5CCSPXyBj8F +JwsAlgorithm.xLibTest > JWS Signature: AR9jA95xrAcWTWOUCnC0usJyyBxFD1scltNF8edU__UiC_gAC6I60EtToalXZeAwkhpn7OiQpd-W9NeHVi8deRGLAMeCGsYJY3b0L3eepuhXQ9xWQ8eTEtGds8JA0xWW-BuwecuPEPBo9VeCS2vmZBdWDlvhxxF1HXRW7VFyUSlXEhOR JwsAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWE_RsaOaepAesGcm_X509.Decrypt > True : {"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ0eXAiOiJKV1QifQ.edcrJWqKOfY080tAusvFJzuprNKTeaw7YILvAyDw_909i5aQ16CK6yuZs2tXd_pRp4UON05_jCNSBwOz-qkMptTjO9UX4B0Ln4LN4UUK-44bPdHWsQHA4-T0OyOHtEcemqElnuWGVL32i6-FmA1hA70OvxzF_DKB6JD65bPV4scfwcaAILySeVzq2Efg3y-6Qu5hOySeT8RLhEH1NAxisTI1jWi5-jIpYHlcRBm5LH25YXiyouc3zxaoZ_8g5dC2D6TTP40CdZBV8IO505FvINHqo6cli7LznVcDjR6AVtsPoBXsuP63GtJA-NCCDSAZ5G8YG3SvZ6LBDO035YClyw.tAX-0ka-sV93KBtw.dRlMYVJtyFL-8JjUiv32PPaE58UGkCnTAFIEAO12ZXSOoqiTS5RG74JRHg.oUbGIhaiV9ohBEMIfuoUWg +JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ0eXAiOiJKV1QifQ.geOgee7QSmQZ6xjSnkr443uRMeZXD3Ell6BHjM2GJb5A2PJYrhfa81TqJhgS9-39zhS46IFC-TDHajA_AZauQSClg4wp1KCsTLkIcUYfxQy9W9hIZChaDe1mIx-cp6V08ZH47W-bNhtsaA0ymOy8rUFrSaAH9PYecGe_KAVt2P-bxsCNuDah_jvK4cCcYRaU9vfYl_xNbRUCBt_pxHGM5xa4NfpJ8XSMlHENOWlXE9w_XcP8zmnyeQBq8DI9jAZ7mIL7Aahq2PjgBAPL2ox0Sok21RfqqgoTHWWVz7nQF4WJcSkyqj3v83faqOIIu__pOdFRDWcrnIC2HnFOzY6C3g.nnIxn0C2F5f5qHRj.8L9GI_I5siR06qkpf0LlQ_NuIbyYPB4MUdpNeK2UodmS_U5wR2mbUvbocw.HDjjTIVn1TcWCwEVvITaKQ JweAlgorithm.xLibTest > JWE Header: {"alg":"RSA-OAEP","enc":"A256GCM","typ":"JWT"} -JweAlgorithm.xLibTest > JWE Encrypted Key: edcrJWqKOfY080tAusvFJzuprNKTeaw7YILvAyDw_909i5aQ16CK6yuZs2tXd_pRp4UON05_jCNSBwOz-qkMptTjO9UX4B0Ln4LN4UUK-44bPdHWsQHA4-T0OyOHtEcemqElnuWGVL32i6-FmA1hA70OvxzF_DKB6JD65bPV4scfwcaAILySeVzq2Efg3y-6Qu5hOySeT8RLhEH1NAxisTI1jWi5-jIpYHlcRBm5LH25YXiyouc3zxaoZ_8g5dC2D6TTP40CdZBV8IO505FvINHqo6cli7LznVcDjR6AVtsPoBXsuP63GtJA-NCCDSAZ5G8YG3SvZ6LBDO035YClyw -JweAlgorithm.xLibTest > JWE Initialization Vector: tAX-0ka-sV93KBtw -JweAlgorithm.xLibTest > JWE Ciphertext: dRlMYVJtyFL-8JjUiv32PPaE58UGkCnTAFIEAO12ZXSOoqiTS5RG74JRHg -JweAlgorithm.xLibTest > JWE Authentication Tag: oUbGIhaiV9ohBEMIfuoUWg +JweAlgorithm.xLibTest > JWE Encrypted Key: geOgee7QSmQZ6xjSnkr443uRMeZXD3Ell6BHjM2GJb5A2PJYrhfa81TqJhgS9-39zhS46IFC-TDHajA_AZauQSClg4wp1KCsTLkIcUYfxQy9W9hIZChaDe1mIx-cp6V08ZH47W-bNhtsaA0ymOy8rUFrSaAH9PYecGe_KAVt2P-bxsCNuDah_jvK4cCcYRaU9vfYl_xNbRUCBt_pxHGM5xa4NfpJ8XSMlHENOWlXE9w_XcP8zmnyeQBq8DI9jAZ7mIL7Aahq2PjgBAPL2ox0Sok21RfqqgoTHWWVz7nQF4WJcSkyqj3v83faqOIIu__pOdFRDWcrnIC2HnFOzY6C3g +JweAlgorithm.xLibTest > JWE Initialization Vector: nnIxn0C2F5f5qHRj +JweAlgorithm.xLibTest > JWE Ciphertext: 8L9GI_I5siR06qkpf0LlQ_NuIbyYPB4MUdpNeK2UodmS_U5wR2mbUvbocw +JweAlgorithm.xLibTest > JWE Authentication Tag: HDjjTIVn1TcWCwEVvITaKQ JweAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JWE_Rsa15A128CbcHS256_X509.Decrypt > True : {"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidHlwIjoiSldUIn0.MtulbY_m_n7EnWKU2JtGFuZhuoz060YvMHGDo7rLsXziHN0rtVQKKbCHzWd9Z3bp_rSr99YeeVaDcJSw0dPKJ9Kwt9g5vdqVHin7exOUmFRH3ELlwL26xKQFyV_Dvx1zmMHiYC4fBJ8lpruojg2Sp3hafdZKKyEDIf7wdOodQITH8oTLl63pwALqGUCxY7BikQgBMnaR74DfbvlfZaGwuqW3_IEonL-wFORjYN7PMEMMhBv3BVXNuJX50TgEU1irazHslIqDvRKNpnXJnCvZYMQHWLZLii1QLkXKNtsm712D8wki0cVT8P3Eeu9EuXX1ndmu6K30jesksmUZzthfUw.C2rFKhxUYzz3UKPKznOBmg.nJ8T8e6NYk5C14Yy1HoIDslMg9mAUuP-FgB-wOXvQ-Pgy4r1wJ80gVa0OgJnpDRO.ua5QHzHyKDD7UwqlxBZkpg +JweAlgorithm.xLibTest > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwidHlwIjoiSldUIn0.JMlf2TS_mhfStFRczhbwvYIcKEUr4USffyFzamCHHYOY87KICbNSGLQZNyhihRYAdlybEHQGMmKPbn8ChWDv8oRXvJJhXac9478NDch9ZGzlFC5W1PW9MA7X1xChhhx6s_g8IqBt7FTsM7oq8C8m74Upn828Ob1DfVGKCRdT9uSsQjtwdPLVXzG9LoQCX6xLMS8UPbyQ_nH0EK3e8dPRDHbFv1q5gaTFN9gHgUP9wf4YUq2iTO1GC9yOyRRrXI_eiYxXrjzeXUZfkIdCpLdZoK1oxxt0XCX75xE9dVPMgH_c-5sBzCDi4l6R2oKvMaVxYzfC2egCwcHlOW2D5Twbrg.eJ2Qx8zJYS5LEcORLiGLVQ.dRIZq1NC3vf8QK322JorFuoi3cZ48-aVaTymQ406a_UcB4yuyKvXGkjXgVpADLIA.kKzhC7akWsJNDlDA7qB51w JweAlgorithm.xLibTest > JWE Header: {"alg":"RSA1_5","enc":"A128CBC-HS256","typ":"JWT"} -JweAlgorithm.xLibTest > JWE Encrypted Key: MtulbY_m_n7EnWKU2JtGFuZhuoz060YvMHGDo7rLsXziHN0rtVQKKbCHzWd9Z3bp_rSr99YeeVaDcJSw0dPKJ9Kwt9g5vdqVHin7exOUmFRH3ELlwL26xKQFyV_Dvx1zmMHiYC4fBJ8lpruojg2Sp3hafdZKKyEDIf7wdOodQITH8oTLl63pwALqGUCxY7BikQgBMnaR74DfbvlfZaGwuqW3_IEonL-wFORjYN7PMEMMhBv3BVXNuJX50TgEU1irazHslIqDvRKNpnXJnCvZYMQHWLZLii1QLkXKNtsm712D8wki0cVT8P3Eeu9EuXX1ndmu6K30jesksmUZzthfUw -JweAlgorithm.xLibTest > JWE Initialization Vector: C2rFKhxUYzz3UKPKznOBmg -JweAlgorithm.xLibTest > JWE Ciphertext: nJ8T8e6NYk5C14Yy1HoIDslMg9mAUuP-FgB-wOXvQ-Pgy4r1wJ80gVa0OgJnpDRO -JweAlgorithm.xLibTest > JWE Authentication Tag: ua5QHzHyKDD7UwqlxBZkpg +JweAlgorithm.xLibTest > JWE Encrypted Key: JMlf2TS_mhfStFRczhbwvYIcKEUr4USffyFzamCHHYOY87KICbNSGLQZNyhihRYAdlybEHQGMmKPbn8ChWDv8oRXvJJhXac9478NDch9ZGzlFC5W1PW9MA7X1xChhhx6s_g8IqBt7FTsM7oq8C8m74Upn828Ob1DfVGKCRdT9uSsQjtwdPLVXzG9LoQCX6xLMS8UPbyQ_nH0EK3e8dPRDHbFv1q5gaTFN9gHgUP9wf4YUq2iTO1GC9yOyRRrXI_eiYxXrjzeXUZfkIdCpLdZoK1oxxt0XCX75xE9dVPMgH_c-5sBzCDi4l6R2oKvMaVxYzfC2egCwcHlOW2D5Twbrg +JweAlgorithm.xLibTest > JWE Initialization Vector: eJ2Qx8zJYS5LEcORLiGLVQ +JweAlgorithm.xLibTest > JWE Ciphertext: dRIZq1NC3vf8QK322JorFuoi3cZ48-aVaTymQ406a_UcB4yuyKvXGkjXgVpADLIA +JweAlgorithm.xLibTest > JWE Authentication Tag: kKzhC7akWsJNDlDA7qB51w JweAlgorithm.xLibTest > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} JwsAlgorithm.none > eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ. JwsAlgorithm.HS256 > Original:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.dvd5Ak6zcBy0OB7gxVtehT3Ab5NO7XEggon6r_CTSfE @@ -149,64 +149,64 @@ JwsAlgorithm.RS256 > JWS Header: {"alg":"RS256","typ":"JWT"} JwsAlgorithm.RS256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} JwsAlgorithm.RS256 > JWS Signature: jMJbrOaZ_p0xouAFfetm_orlTuwPbJK65-rEto5lIGgCR_oCG_ApQWeCXc5xikto_IcN2nNsHWMOMJMII6WlhVmn9pFTuuj-fZH_aB-aasDSguyXd59BA43a4glZbPCITOwZFfeNMpXGrKG_YNvexP5mtiJYYCDXMgq2zBHS9lQYcGXy4YyGPD_jNu6ziLRNDdKCkRqTppTE2SexZAwaSJRGGuY-fHA3jVPBV90Cty7yBC3ybKmiE4imVQs8CUw7ic61HSytgItIlreol4PMMP8fXB6O1e_K8QJFfRIf9oC07y9Mo5OWl4CCOxvKAo9nos0GTWUUNUH-sugJhUV14A JwsAlgorithm.RS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.6TPKtvEBm2VHxGa_9fexyxV7_AfAz-eyJORBoxJdy2oI7viElhe_deqp8lM-15lAZmmJU9iIm7u7ykztquH2sQ +JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.H0iOBZCtxT_AVfNdJldaNFP5jkQ0CsIxg9m4skkUXu_P0jB6PS8qaw_XRAsWh6Qcg4m5avODmjy0EDSd2ele_g JwsAlgorithm.ES256 > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.ES256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > JWS Signature: 6TPKtvEBm2VHxGa_9fexyxV7_AfAz-eyJORBoxJdy2oI7viElhe_deqp8lM-15lAZmmJU9iIm7u7ykztquH2sQ +JwsAlgorithm.ES256 > JWS Signature: H0iOBZCtxT_AVfNdJldaNFP5jkQ0CsIxg9m4skkUXu_P0jB6PS8qaw_XRAsWh6Qcg4m5avODmjy0EDSd2ele_g JwsAlgorithm.ES256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.GeRBw5SiQhVB1chhNwVA-xMKmWr6YGkfEY6VTWGGRUGQLmlqpTV6G85v_aJRvw6ob-yVbhZvPmqXJwUtayRalA +JwsAlgorithm.ES256 > Original:eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.RQAKLvmkvFqF-TI_djlBXW5_XXjZA8Q15uBvcGz_GZhhTzksxD9AddQIN_jWRIyXcbd_U1EvDtK-d_Qt9_MWNA JwsAlgorithm.ES256 > JWS Header: {"alg":"ES256","typ":"JWT"} JwsAlgorithm.ES256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":1300819380} -JwsAlgorithm.ES256 > JWS Signature: GeRBw5SiQhVB1chhNwVA-xMKmWr6YGkfEY6VTWGGRUGQLmlqpTV6G85v_aJRvw6ob-yVbhZvPmqXJwUtayRalA +JwsAlgorithm.ES256 > JWS Signature: RQAKLvmkvFqF-TI_djlBXW5_XXjZA8Q15uBvcGz_GZhhTzksxD9AddQIN_jWRIyXcbd_U1EvDtK-d_Qt9_MWNA JwsAlgorithm.ES256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.kKCM3QOB7PjZXcQmL3XE3HKb2LPsn_HAXS3GpW9t2yrh6frqciP4MHr8S5S9O0BkZlWzf7fUivZ2auyNow7fuBGynihTn9vVOCMKI12k_LCkdnMdgE52rxnr_tfdhqGlikNQvPIiWLxa1q43ywnFvdZvmx5VaRZzCDFyJm9pL1F0e_iXdz4hzybOuOOXN5fQ3hih7PJmtRyos1CEa86wegiTD6BeYIbJgajWuUMw7jLAPllLzbD4m1s-FCCowZyni53HxLCercOu4Oc3t-jzTYZju_apELrPJ7y0RYPcTzU4TSnuEoTtznYUw1Ls-_ceztoNt5j3Mxp-FMIhFXnZPw.GN3QJ5vAsUq3T5XNzLhuWg.DgxbAehLvwTYErc9-wzpeAnND6hVMuAndrmwyKMaIFHnNoEupw471xHGonsdZt-c.S6y4xWqM7OwMfuO66MlM-A +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.OzcYE-A6g9ZYTzefwQEtmZSzLRR9kdiGyvlYSZUGA4LRkMjBXM5P-hwHkoOWbJolGurkSonkyTWgNU-YeKeiCZjqtkSNSuOSMsAgcJEWX6J1ln4m226DIyEvAUJmFvnEEe6UMv4yO2djsq4dWyrb_QmdHXrqfVeas2yKQjPpciXt1hmRaYe4IBFHd_VSDy4k1aiGMzH53_DJWZwIQbVt99Ev1Kr5uw4GFDkc82zChGOxQpLo2ErCh9vxRSqkWamq464fMcc2bYihZ7jPOgZ2PpBrjY1y2xKwxWHxvew4u2anQjL6k4H8gvs2BundU2kPB5AlIRYSdbtlii0QMbqKJQ.ZVehMkv6mUe3xh5R3afWmQ.s1o-2B-bnGT3-WRrzELJBn-yLfPhOeJmqYpQ90tkc1qzWFlvzk5V37N6J965T2uB.WpKxJqnNmK7y7FKPHdS7hg JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Header: {"alg":"RSA1_5","enc":"A128CBC-HS256"} -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: kKCM3QOB7PjZXcQmL3XE3HKb2LPsn_HAXS3GpW9t2yrh6frqciP4MHr8S5S9O0BkZlWzf7fUivZ2auyNow7fuBGynihTn9vVOCMKI12k_LCkdnMdgE52rxnr_tfdhqGlikNQvPIiWLxa1q43ywnFvdZvmx5VaRZzCDFyJm9pL1F0e_iXdz4hzybOuOOXN5fQ3hih7PJmtRyos1CEa86wegiTD6BeYIbJgajWuUMw7jLAPllLzbD4m1s-FCCowZyni53HxLCercOu4Oc3t-jzTYZju_apELrPJ7y0RYPcTzU4TSnuEoTtznYUw1Ls-_ceztoNt5j3Mxp-FMIhFXnZPw -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: GN3QJ5vAsUq3T5XNzLhuWg -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Ciphertext: DgxbAehLvwTYErc9-wzpeAnND6hVMuAndrmwyKMaIFHnNoEupw471xHGonsdZt-c -JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: S6y4xWqM7OwMfuO66MlM-A +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: OzcYE-A6g9ZYTzefwQEtmZSzLRR9kdiGyvlYSZUGA4LRkMjBXM5P-hwHkoOWbJolGurkSonkyTWgNU-YeKeiCZjqtkSNSuOSMsAgcJEWX6J1ln4m226DIyEvAUJmFvnEEe6UMv4yO2djsq4dWyrb_QmdHXrqfVeas2yKQjPpciXt1hmRaYe4IBFHd_VSDy4k1aiGMzH53_DJWZwIQbVt99Ev1Kr5uw4GFDkc82zChGOxQpLo2ErCh9vxRSqkWamq464fMcc2bYihZ7jPOgZ2PpBrjY1y2xKwxWHxvew4u2anQjL6k4H8gvs2BundU2kPB5AlIRYSdbtlii0QMbqKJQ +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: ZVehMkv6mUe3xh5R3afWmQ +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Ciphertext: s1o-2B-bnGT3-WRrzELJBn-yLfPhOeJmqYpQ90tkc1qzWFlvzk5V37N6J965T2uB +JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: WpKxJqnNmK7y7FKPHdS7hg JweAlgorithm.RSA1_5, JweEncryption.A128CBC_HS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.GnmWpfccMRweSdfgnpiEwlhmEAqGMDnwMG4RryLDoHS3SkhhOJ-FVeMUVUoeuIEsXbR_Ea5qg7p9TziXaH8EwiQcClkAkgdn0Fmo51IQ2CoRnleGbF9ysq7Ppr5urPozDvBO9mDrIbAwBY4Q0OVlVio7VUo5sg7UVkM42aR3M7k-KJdyoJLQsHkF6skSyLnajNs9Gc5iozXmK5fpcYqTVhgl0PdazntTxQuvN1ileg5yORvveQ-0zOR4oa0udyJULTeAjWhEfYEopLihNAnGGWj7P_GdvnGCw9W_Y8OMXnR3GJw76l82sWdB53KZlNLtjXWJo37oKQjnWuvjcqtpEw.A2aMGxvBXSlRNG9C.s4J3soaCmwKTJzR2KsxOIuvT5Bj4fevMCtQ6ky4tNB7ZJzqW8HH1hP3qbA.ha1fZH4ofYZlGxYMBf1Xaw +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Original:eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.LvN6VTWMjMZpqe0V5G7Zt4AR9jysty1DobLoPOkL4yZvOrskEX7XmWedxM0S0PdxzqKDC5Hid5ydUQAQFX9Pa1Yg5Ieq5qh93bh0ZSK9vU1Ddvp8r-SwVbksrNmC7l1hX3b3SsOcHh1Isf7wykoA2VTXoRfkkG_7emLVfe2N4_cxJgyvYPCCyrOPOt2c-MStXIsAQZUArcE0J7Kh7gY1BqETo0uYGGV0NV4A57QnWy8OwDTfTLxj_REs-5ru_zb6HUnpU3aKalkcBMsnoRoJm0W8-ypx-fv0SRpdHBL3lL-FgPhpttF-RuipZ9XjZDH5fHKoK3HbzNz_NQpK5ogbNQ.RZKs1OvASljzSnbj.D_jO0Mck_HY-LdA3j7v_USGhENK2LKQEwX5HQD-mmjr_bW5V0PnlWiwqoQ.EJEwsbQ2TF9gEz3vQm-nyA JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Header: {"alg":"RSA-OAEP","enc":"A256GCM"} -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Encrypted Key: GnmWpfccMRweSdfgnpiEwlhmEAqGMDnwMG4RryLDoHS3SkhhOJ-FVeMUVUoeuIEsXbR_Ea5qg7p9TziXaH8EwiQcClkAkgdn0Fmo51IQ2CoRnleGbF9ysq7Ppr5urPozDvBO9mDrIbAwBY4Q0OVlVio7VUo5sg7UVkM42aR3M7k-KJdyoJLQsHkF6skSyLnajNs9Gc5iozXmK5fpcYqTVhgl0PdazntTxQuvN1ileg5yORvveQ-0zOR4oa0udyJULTeAjWhEfYEopLihNAnGGWj7P_GdvnGCw9W_Y8OMXnR3GJw76l82sWdB53KZlNLtjXWJo37oKQjnWuvjcqtpEw -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Initialization Vector: A2aMGxvBXSlRNG9C -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Ciphertext: s4J3soaCmwKTJzR2KsxOIuvT5Bj4fevMCtQ6ky4tNB7ZJzqW8HH1hP3qbA -JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Authentication Tag: ha1fZH4ofYZlGxYMBf1Xaw +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Encrypted Key: LvN6VTWMjMZpqe0V5G7Zt4AR9jysty1DobLoPOkL4yZvOrskEX7XmWedxM0S0PdxzqKDC5Hid5ydUQAQFX9Pa1Yg5Ieq5qh93bh0ZSK9vU1Ddvp8r-SwVbksrNmC7l1hX3b3SsOcHh1Isf7wykoA2VTXoRfkkG_7emLVfe2N4_cxJgyvYPCCyrOPOt2c-MStXIsAQZUArcE0J7Kh7gY1BqETo0uYGGV0NV4A57QnWy8OwDTfTLxj_REs-5ru_zb6HUnpU3aKalkcBMsnoRoJm0W8-ypx-fv0SRpdHBL3lL-FgPhpttF-RuipZ9XjZDH5fHKoK3HbzNz_NQpK5ogbNQ +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Initialization Vector: RZKs1OvASljzSnbj +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Ciphertext: D_jO0Mck_HY-LdA3j7v_USGhENK2LKQEwX5HQD-mmjr_bW5V0PnlWiwqoQ +JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > JWE Authentication Tag: EJEwsbQ2TF9gEz3vQm-nyA JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..QVrifvtI6I5Ooo9TD4zhXA.Fi6y6jUXoIhF-ewFpjpunvykW32AuSsg19ucWGcKBe41s7mlurF_YrS9-xEkyjkq.nkhS-2r8JYDiWAnwKg3inQ +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Original:eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..XutFFx26mtPmMvtNf65nLg.DCzPd_4omz_ei3EgKCz52P8GFgu2UXQ2bNrhyFnbclfdb-mdEeCZudeDF2U7WWhT.0WNn7BUIeKc06k49IDimQQ JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Header: {"alg":"dir","enc":"A128CBC-HS256"} JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Encrypted Key: -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: QVrifvtI6I5Ooo9TD4zhXA -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Ciphertext: Fi6y6jUXoIhF-ewFpjpunvykW32AuSsg19ucWGcKBe41s7mlurF_YrS9-xEkyjkq -JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: nkhS-2r8JYDiWAnwKg3inQ +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Initialization Vector: XutFFx26mtPmMvtNf65nLg +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Ciphertext: DCzPd_4omz_ei3EgKCz52P8GFgu2UXQ2bNrhyFnbclfdb-mdEeCZudeDF2U7WWhT +JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > JWE Authentication Tag: 0WNn7BUIeKc06k49IDimQQ JweAlgorithm.DIR, JweEncryption.A128CBC_HS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.I53ooLjzbWEV1c5y53IPg_J18hmJY7MXT_tdTPmJwqP1qZrM0xGiE-Z-V8X_nPpuRYgTfn184cmkaZ7n_dyzejPha9mWLRaM.zuo1PwH-b-c0plvEFtUMBg.bDmhsw1maPd2n3rBNqGqLJOBtWvpjZwyeHQIVO7roT08oweVA22XxCZOy4rpgeNC.4Bcb4-P2IayzjV4lKOkLGFZJ_4W-wO_f3ic2hIirZIw +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0._qfrZ_cxhhLJKp-PWjYdJ4D0PvI_dN-Ss5nLkb7itnu6kN1ZjR4DLCfLxYlfqRQOE-WyBdBfj6hewJrJoSHRVwDtAAR0FKYZ.ujhq-rKSxYV4eFSZMCc_CQ.Kmha4Yv_artaGFkKarp1m-SCaqEM_XSwmpSZtwA2XnbL0eEtpc6PEJP3EYFV20KO.pF1Qj43e8PaStatSvkKAgmQXgBNfKFdTlbhC_S5Ghrg JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256KW","enc":"A256CBC-HS512"} -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: I53ooLjzbWEV1c5y53IPg_J18hmJY7MXT_tdTPmJwqP1qZrM0xGiE-Z-V8X_nPpuRYgTfn184cmkaZ7n_dyzejPha9mWLRaM -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: zuo1PwH-b-c0plvEFtUMBg -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: bDmhsw1maPd2n3rBNqGqLJOBtWvpjZwyeHQIVO7roT08oweVA22XxCZOy4rpgeNC -JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: 4Bcb4-P2IayzjV4lKOkLGFZJ_4W-wO_f3ic2hIirZIw +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: _qfrZ_cxhhLJKp-PWjYdJ4D0PvI_dN-Ss5nLkb7itnu6kN1ZjR4DLCfLxYlfqRQOE-WyBdBfj6hewJrJoSHRVwDtAAR0FKYZ +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: ujhq-rKSxYV4eFSZMCc_CQ +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: Kmha4Yv_artaGFkKarp1m-SCaqEM_XSwmpSZtwA2XnbL0eEtpc6PEJP3EYFV20KO +JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: pF1Qj43e8PaStatSvkKAgmQXgBNfKFdTlbhC_S5Ghrg JweAlgorithm.A256KW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2R0NNS1ciLCJpdiI6IkQ2bUVlLXV3bUw1VEV3dUEiLCJ0YWciOiJOMGRSQV9JUEhhQndjeG9WT3BFYjlBIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiJ9.14yQsB8He2E6eRQTLWaFKyXG6KHtHoWNBswgJfmbDd93g1ioi_ukxXsgo9WSqxme0m-WoVenxSOhZJwk9s6Zrw.6tyAe7zEnsAMIzF_1z_9Nw.sg5995L8QkvHBRoUr4rzNVUhIv-AdNSzgQozFPpAV-9rwbQsrKaO2TJILNGTuKjK.dzRekdA9FNlluMu3hZF9nJWgtxLWWl1gJIUnjMjywJU -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256GCMKW","iv":"D6mEe-uwmL5TEwuA","tag":"N0dRA_IPHaBwcxoVOpEb9A","enc":"A256CBC-HS512"} -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: 14yQsB8He2E6eRQTLWaFKyXG6KHtHoWNBswgJfmbDd93g1ioi_ukxXsgo9WSqxme0m-WoVenxSOhZJwk9s6Zrw -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: 6tyAe7zEnsAMIzF_1z_9Nw -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: sg5995L8QkvHBRoUr4rzNVUhIv-AdNSzgQozFPpAV-9rwbQsrKaO2TJILNGTuKjK -JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: dzRekdA9FNlluMu3hZF9nJWgtxLWWl1gJIUnjMjywJU +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJBMjU2R0NNS1ciLCJpdiI6ImFpRTQ0a2xHOVgwZkVvV1kiLCJ0YWciOiJ3d1hPN1J5cllnZkViekI1QXhZUU5BIiwiZW5jIjoiQTI1NkNCQy1IUzUxMiJ9.cnb-PCDV7UYDoMw0g_yVwxsIt4ZKvaMjmPPt-W-W5umKn-R-2XH8KPV3UD0F8ZGNxxsGY5OlWwJux_uYkaaWpw.bTyoLu-X_kTjWY2Rc83syg.AQGbsWNadOpxDiNpQ4rNhO9NSGW7Zl2ESGZ9fpgoeSdf9Uxv0SxTrGVneGRfEn2s.BdpMmE7RHfonlXj9GB8YHEe1TbOPeYqfSqN88le-JhY +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"A256GCMKW","iv":"aiE44klG9X0fEoWY","tag":"wwXO7RyrYgfEbzB5AxYQNA","enc":"A256CBC-HS512"} +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: cnb-PCDV7UYDoMw0g_yVwxsIt4ZKvaMjmPPt-W-W5umKn-R-2XH8KPV3UD0F8ZGNxxsGY5OlWwJux_uYkaaWpw +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: bTyoLu-X_kTjWY2Rc83syg +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: AQGbsWNadOpxDiNpQ4rNhO9NSGW7Zl2ESGZ9fpgoeSdf9Uxv0SxTrGVneGRfEn2s +JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: BdpMmE7RHfonlXj9GB8YHEe1TbOPeYqfSqN88le-JhY JweAlgorithm.A256GCMKW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > Original:eyJhbGciOiJFQ0RILUVTIiwiZXBrIjp7Imt0eSI6IkVDIiwieCI6IldwbGRSQkJBWktxSktncndpMk56UGplRHdCek1tY09Dd1ZYWUFSb3hqSFUiLCJ5IjoiSUdCRXZXUEtCZEdDQUtoOVc3NVg0bHRXelg0YThJbVR6RW9fb2hlOXVUTSIsImNydiI6IlAtMjU2In0sImVuYyI6IkEyNTZHQ00ifQ..EcC8NIJuuSwfBLOR.u8-_yuTuxDd89ZfP7PumVfgMaqFPJ6Rm5DSfiJZAgSUnEyXg0gHK5HwGwg.g1L4cz-kr2uBf-Tcn_K9cA -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Header: {"alg":"ECDH-ES","epk":{"kty":"EC","x":"WpldRBBAZKqJKgrwi2NzPjeDwBzMmcOCwVXYARoxjHU","y":"IGBEvWPKBdGCAKh9W75X4ltWzX4a8ImTzEo_ohe9uTM","crv":"P-256"},"enc":"A256GCM"} +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > Original:eyJhbGciOiJFQ0RILUVTIiwiZXBrIjp7Imt0eSI6IkVDIiwieCI6IjJIclBMemFZaWdlTjBpMVhSekZhSVhSeHhRZmwzeVJpSW9STW0yREVaY00iLCJ5IjoiZURYQnpVOG5tYUxQYUtRZFRmU3liaW82M2NYRkZhUm1aSHZLRzNuSUc5OCIsImNydiI6IlAtMjU2In0sImVuYyI6IkEyNTZHQ00ifQ..lo8PtjHEt67bW4qx.4f1tURxszVi_SH3k4d777dzS3ZMZ2O64d-MPdZAx22ndvkdPZdJP6ZT30w.C7gahE38EkYM9J3srZjsng +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Header: {"alg":"ECDH-ES","epk":{"kty":"EC","x":"2HrPLzaYigeN0i1XRzFaIXRxxQfl3yRiIoRMm2DEZcM","y":"eDXBzU8nmaLPaKQdTfSybio63cXFFaRmZHvKG3nIG98","crv":"P-256"},"enc":"A256GCM"} JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Encrypted Key: -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Initialization Vector: EcC8NIJuuSwfBLOR -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Ciphertext: u8-_yuTuxDd89ZfP7PumVfgMaqFPJ6Rm5DSfiJZAgSUnEyXg0gHK5HwGwg -JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Authentication Tag: g1L4cz-kr2uBf-Tcn_K9cA +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Initialization Vector: lo8PtjHEt67bW4qx +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Ciphertext: 4f1tURxszVi_SH3k4d777dzS3ZMZ2O64d-MPdZAx22ndvkdPZdJP6ZT30w +JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > JWE Authentication Tag: C7gahE38EkYM9J3srZjsng JweAlgorithm.ECDH_ES, JweEncryption.A256GCM > System.Security.Cryptography.CryptographicException, キーがありません。 -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJwMmMiOjgxOTIsInAycyI6IlJ2VmZvc1Nua0Vxb3FpMFEiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.3PB8TgWzRJbc__0yLUZ8KFnmFvTJbhNcHm7K523OjNUIDkFRP7nMIn8PQkbWf4eB8sTAArTotqeXSAN8sC8M7TSS_TkRCCAJ.zNB4bHGogG5K3mdQnG7_Rg.TS0HPoeZo6J9pgu6udaXfggeBvN13ppquLXqbF5OqSUbA3H-r69sd0yVN1urTNOF.SOj1Cl58MzoMN3Itu5vzoiotjPS3hudXlZ4XBXYgo8s -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"PBES2-HS256+A128KW","p2c":8192,"p2s":"RvVfosSnkEqoqi0Q","enc":"A256CBC-HS512"} -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: 3PB8TgWzRJbc__0yLUZ8KFnmFvTJbhNcHm7K523OjNUIDkFRP7nMIn8PQkbWf4eB8sTAArTotqeXSAN8sC8M7TSS_TkRCCAJ -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: zNB4bHGogG5K3mdQnG7_Rg -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: TS0HPoeZo6J9pgu6udaXfggeBvN13ppquLXqbF5OqSUbA3H-r69sd0yVN1urTNOF -JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: SOj1Cl58MzoMN3Itu5vzoiotjPS3hudXlZ4XBXYgo8s +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Original:eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJwMmMiOjgxOTIsInAycyI6IkluMHUtMEF4WHlnSWMtMUIiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.M7imMeHOCDdpQR7z4dmIIozsqP27l6u7oHrbwnomo6DAOxuW8vtgGwnGPxuk2_0cHvaugdVOkCEydmdRMuiqGgsfK1IB7XQ8.NwA4YIYO_d4vwOmZOIF4lg.RY2xyM9bfZ1uZBzCAbDJOoHhWVqV4h5Q4ywVvTIv34EkVHkmiAWWuDkybFevVB1f.MlYlK8ISJItfLal-f3hTWKyIwrIcA2ygAjA66PVcJXQ +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Header: {"alg":"PBES2-HS256+A128KW","p2c":8192,"p2s":"In0u-0AxXygIc-1B","enc":"A256CBC-HS512"} +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Encrypted Key: M7imMeHOCDdpQR7z4dmIIozsqP27l6u7oHrbwnomo6DAOxuW8vtgGwnGPxuk2_0cHvaugdVOkCEydmdRMuiqGgsfK1IB7XQ8 +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Initialization Vector: NwA4YIYO_d4vwOmZOIF4lg +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Ciphertext: RY2xyM9bfZ1uZBzCAbDJOoHhWVqV4h5Q4ywVvTIv34EkVHkmiAWWuDkybFevVB1f +JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > JWE Authentication Tag: MlYlK8ISJItfLal-f3hTWKyIwrIcA2ygAjA66PVcJXQ JweAlgorithm.PBES2_HS256_A128KW, JweEncryption.A256CBC_HS512 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} Adding extra headers to RS256 > Original:eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6IkpXVCIsImtleWlkIjoiMTExLTIyMi0zMzMifQ.eyJzdWIiOiJtci54QGNvbnRvc28uY29tIiwiZXhwIjoxMzAwODE5MzgwfQ.KwtpHrjNKBnyHo6QRaULxcWZDF9mDKHiQG1QBSmnrwHi7vJSiLH_3fFIcTkQvdu7FstmPOuuVD-T3EPKfv61aHz5o-0dRTylooln5tS_2_uZ4lPV4A2C_Pr_cYzRawUIuTwhCi3n0i-fQapYvKT41qjh0vKalEuDmd6-WDnpGcKdI3dv-kSB_42FfIdbEKDEtYvgyzwj5An9YJim29OsiM-GW6tyqei3nzHrQ0yPhgfKOd89M_azGynAVTTNKvPyZujnILu-XnVu54So-5W2fwg-WkKIpvP2ZZFAWRs-DEapBJWrNm10GGZdid-98SmGoifkaDNpCeIcQe3uetDB6w Adding extra headers to RS256 > JWS Header: {"alg":"RS256","typ":"JWT","cty":"JWT","keyid":"111-222-333"} @@ -214,4 +214,4 @@ Adding extra headers to RS256 > JWS Payload: {"sub":"mr.x@contoso.com","exp":130 Adding extra headers to RS256 > JWS Signature: KwtpHrjNKBnyHo6QRaULxcWZDF9mDKHiQG1QBSmnrwHi7vJSiLH_3fFIcTkQvdu7FstmPOuuVD-T3EPKfv61aHz5o-0dRTylooln5tS_2_uZ4lPV4A2C_Pr_cYzRawUIuTwhCi3n0i-fQapYvKT41qjh0vKalEuDmd6-WDnpGcKdI3dv-kSB_42FfIdbEKDEtYvgyzwj5An9YJim29OsiM-GW6tyqei3nzHrQ0yPhgfKOd89M_azGynAVTTNKvPyZujnILu-XnVu54So-5W2fwg-WkKIpvP2ZZFAWRs-DEapBJWrNm10GGZdid-98SmGoifkaDNpCeIcQe3uetDB6w Adding extra headers to RS256 > Decoded:{"sub":"mr.x@contoso.com","exp":1300819380} Strict validation(RS256) > {"sub":"mr.x@contoso.com","exp":1300819380} -Verify nested signedXml > True : <?xml version="1.0" encoding="utf-8"?><xml><a ID="a"><b ID="b"><c /><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#b"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>+sg4j+LFYSzu6ZSzp2Jrh7CxLATJlNH/KTEQlXcfmtM=</DigestValue></Reference></SignedInfo><SignatureValue>GBYFP0HPapV9CBUVsWWnokOhEWkJeTIVf8U3hy3DxPNUiqungv6jcfVmYPEazzjkSkxvVEEPZZ8tCr6fiWHl2Mlm/9zMwfFDX3pxsNirtkAMTk73xwajGw6SB+NQiA1NgG21TabU4S6CVoQGdW9zAUSYqQ/K/6b8uu+z26uEad0=</SignatureValue></Signature></b><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#a"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>gOyUYjJl2u0ljtYCKT6it/xfIC45SQUR6RUTq6ngLk4=</DigestValue></Reference></SignedInfo><SignatureValue>saT83xL1EoONw2q22s+t1k6vO29mt/znMYNChyOUhJPsY5VWpwWPBBkYEPCFZGLMK2pz6yyv3b3AbyfueGL+kf43ePkOzCeZlYx87j3bG6nKT1FEsIl89LUdVSv+x76WrZM73tb4ZOeQKbF03WIrwHmVyp0OmPuZyeCpnof7/Sk=</SignatureValue></Signature></a></xml> +Verify nested signedXml > True : <?xml version="1.0" encoding="utf-8"?><xml><a ID="a"><b ID="b"><c /><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#b"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>+sg4j+LFYSzu6ZSzp2Jrh7CxLATJlNH/KTEQlXcfmtM=</DigestValue></Reference></SignedInfo><SignatureValue>WHZu43d8zzmEIDMudKrMcymywvCWC5mYJnaW1AjzRs5+ZUOLNKTo0FZGPNyMhgOHoEfo+kWjCEb8aU91ptrloHZxt7Z+cKyfpdCbGg/k3t/VvIVvZY43FgYLx60y8Ev1/C9JiySDIbYCcbyaeg3j2FFtQ6rPnIa8vMACstIXpFI=</SignatureValue></Signature></b><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#a"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>D3/L20rnMMSdRtK1VIkBZ2m407nzkRPT0aFbyY1i16Q=</DigestValue></Reference></SignedInfo><SignatureValue>lXekl5vw9tOn54wzN5F4YLWLD9a1W4nQ/nb0aa6vNzmmuo3THD5ITlPfSnCrMo6096xUSwsLWKV+b9y4wmJS7W+69aR9+3y2KMJiv0LofJ8YdukvdHd1nuXV9K5z03OaK86UyHfnL652YRk5YfouqGpi3YaK9P8xtCborAtjoSU=</SignatureValue></Signature></a></xml> diff --git a/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatch48.txt b/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatch48.txt index 7aedc7544..ac5474b39 100644 --- a/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatch48.txt +++ b/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatch48.txt @@ -69,7 +69,7 @@ log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.Level log4net: Created Appender [OPERATION2] log4net: Adding appender named [OPERATION2] to logger [OPERATION]. log4net: Hierarchy Threshold [] -[2025/11/18 15:19:08,286],[INFO ],[1],,,,----->>,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatch\bin\Debug\SimpleBatch.exe,-,SelectCount,SQL%individual%static%- +[2026/08/02 03:26:06,745],[INFO ],[1],,,,----->>,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatch\bin\Debug\SimpleBatch.exe,-,SelectCount,SQL%individual%static%- log4net: configuring repository [log4net-default-repository] using stream log4net: loading XML configuration log4net: Configuring Repository [log4net-default-repository] @@ -144,6 +144,6 @@ log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.Level log4net: Created Appender [OPERATION2] log4net: Adding appender named [OPERATION2] to logger [OPERATION]. log4net: Hierarchy Threshold [] -[2025/11/18 15:19:08,522],[INFO ],[1],153,109,[commandText]:SELECT COUNT(*) FROM Shippers [commandParameter]: -[2025/11/18 15:19:08,523],[INFO ],[1],,,,<<-----,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatch\bin\Debug\SimpleBatch.exe,-,SelectCount,SQL%individual%static%-,214,172 +[2026/08/02 03:26:06,864],[INFO ],[1],85,78,[commandText]:SELECT COUNT(*) FROM Shippers [commandParameter]: +[2026/08/02 03:26:06,866],[INFO ],[1],,,,<<-----,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatch\bin\Debug\SimpleBatch.exe,-,SelectCount,SQL%individual%static%-,108,94 3件のデータがあります diff --git a/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatchCore100.txt b/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatchCore100.txt index 6c070d34d..4cf192639 100644 --- a/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatchCore100.txt +++ b/root/programs/CS/Frameworks/Tests/TestBatch/ResultSimpleBatchCore100.txt @@ -69,7 +69,7 @@ log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.Level log4net: Created Appender [OPERATION2] log4net: Adding appender named [OPERATION2] to logger [OPERATION]. log4net: Hierarchy Threshold [] -[2025/11/18 15:19:19,105],[INFO ],[2],,,,----->>,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatchCore\bin\Debug\net10.0\SimpleBatchCore.dll,-,SelectCount,SQL%individual%static%- +[2026/08/02 03:26:09,480],[INFO ],[2],,,,----->>,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatchCore\bin\Debug\net10.0\SimpleBatchCore.dll,-,SelectCount,SQL%individual%static%- log4net: configuring repository [log4net-default-repository] using stream log4net: loading XML configuration log4net: Configuring Repository [log4net-default-repository] @@ -144,6 +144,6 @@ log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.Level log4net: Created Appender [OPERATION2] log4net: Adding appender named [OPERATION2] to logger [OPERATION]. log4net: Hierarchy Threshold [] -[2025/11/18 15:19:19,225],[INFO ],[2],67,,[commandText]:SELECT COUNT(*) FROM Shippers [commandParameter]: -[2025/11/18 15:19:19,227],[INFO ],[2],,,,<<-----,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatchCore\bin\Debug\net10.0\SimpleBatchCore.dll,-,SelectCount,SQL%individual%static%-,97, +[2026/08/02 03:26:09,569],[INFO ],[2],57,,[commandText]:SELECT COUNT(*) FROM Shippers [commandParameter]: +[2026/08/02 03:26:09,570],[INFO ],[2],,,,<<-----,C:\OpenTouryo\root\programs\CS\Frameworks\Tests\TestBatch\SimpleBatchCore\bin\Debug\net10.0\SimpleBatchCore.dll,-,SelectCount,SQL%individual%static%-,78, 3件のデータがあります diff --git a/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatch/SimpleBatch.csproj b/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatch/SimpleBatch.csproj index 43d57c2f9..2bece7770 100644 --- a/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatch/SimpleBatch.csproj +++ b/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatch/SimpleBatch.csproj @@ -101,7 +101,7 @@ </ItemGroup> <ItemGroup> <PackageReference Include="log4net"> - <Version>3.1.0</Version> + <Version>3.3.0</Version> </PackageReference> <PackageReference Include="Microsoft.Data.SqlClient"> <Version>6.0.2</Version> diff --git a/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatchCore/SimpleBatchCore.csproj b/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatchCore/SimpleBatchCore.csproj index 3107c6493..5c52739ed 100644 --- a/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatchCore/SimpleBatchCore.csproj +++ b/root/programs/CS/Frameworks/Tests/TestBatch/SimpleBatchCore/SimpleBatchCore.csproj @@ -17,7 +17,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="log4net" Version="3.1.0" /> + <PackageReference Include="log4net" Version="3.3.0" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.6" /> diff --git a/root/programs/CS/Frameworks/Tests/TestCode/Program.cs b/root/programs/CS/Frameworks/Tests/TestCode/Program.cs index 23427e9d7..bd31f9cd0 100644 --- a/root/programs/CS/Frameworks/Tests/TestCode/Program.cs +++ b/root/programs/CS/Frameworks/Tests/TestCode/Program.cs @@ -58,6 +58,10 @@ public static void Main(string[] args) MyDebug.OutputDebugAndConsole("----------------------------------------------------------------------------------------------------"); TestDeflateCompression.Root(); #endregion + #region Db + MyDebug.OutputDebugAndConsole("----------------------------------------------------------------------------------------------------"); + TestSQLUtility.Root(); + #endregion #endregion #region Business diff --git a/root/programs/CS/Frameworks/Tests/TestCode/Result48.txt b/root/programs/CS/Frameworks/Tests/TestCode/Result48.txt index bd93ca737..ab39c07ef 100644 --- a/root/programs/CS/Frameworks/Tests/TestCode/Result48.txt +++ b/root/programs/CS/Frameworks/Tests/TestCode/Result48.txt @@ -70,11 +70,11 @@ log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.Level log4net: Created Appender [OPERATION2] log4net: Adding appender named [OPERATION2] to logger [OPERATION]. log4net: Hierarchy Threshold [] -[2025/11/18 15:17:57,158],[DEBUG],[1],LogIF.DebugLog("ACCESS"); -[2025/11/18 15:17:57,174],[INFO ],[1],LogIF.InfoLog("ACCESS"); -[2025/11/18 15:17:57,175],[WARN ],[1],LogIF.WarnLog("ACCESS"); -[2025/11/18 15:17:57,175],[ERROR],[1],LogIF.ErrorLog("ACCESS"); -[2025/11/18 15:17:57,175],[FATAL],[1],LogIF.FatalLog("ACCESS"); +[2026/08/02 08:44:05,979],[DEBUG],[1],LogIF.DebugLog("ACCESS"); +[2026/08/02 08:44:05,991],[INFO ],[1],LogIF.InfoLog("ACCESS"); +[2026/08/02 08:44:05,991],[WARN ],[1],LogIF.WarnLog("ACCESS"); +[2026/08/02 08:44:05,992],[ERROR],[1],LogIF.ErrorLog("ACCESS"); +[2026/08/02 08:44:05,992],[FATAL],[1],LogIF.FatalLog("ACCESS"); ---------------------------------------------------------------------------------------------------- GetMessage: ~メッセージID:I0001に対応する記述(正常系)~ GetMessage: ~メッセージID:E0001に対応する記述(異常系)~ @@ -2301,4 +2301,108 @@ DeflateCompression(FileStream)-2 > is working properly. -------------------------------------------------- DeflateCompression(MemoryStream) > is working properly. ---------------------------------------------------------------------------------------------------- +SQLUtility.GetUpdateSQLParts +[単一主キー] +- SQLServer +UPDATE Orders SET [Qty] = 100, [Note] = Convert(nvarchar(1), 'a') WHERE [OrderID] = 1 +UPDATE Orders SET [Qty] = 200, [Note] = Convert(nvarchar(1), 'b') WHERE [OrderID] = 2 +- Oracle +UPDATE Orders SET "Qty" = 100, "Note" = CAST('a' AS varchar2(1)) WHERE "OrderID" = 1 +UPDATE Orders SET "Qty" = 200, "Note" = CAST('b' AS varchar2(1)) WHERE "OrderID" = 2 +- PstGrS +UPDATE Orders SET "Qty" = CASE + WHEN "OrderID" = 1 THEN 100 + WHEN "OrderID" = 2 THEN 200 + ELSE "Qty" + END, + "Note" = CASE + WHEN "OrderID" = 1 THEN Cast('a' as text) + WHEN "OrderID" = 2 THEN Cast('b' as text) + ELSE "Note" + END +WHERE ("OrderID" = 1) + OR ("OrderID" = 2) +- MySQL +UPDATE Orders SET `Qty` = CASE + WHEN `OrderID` = 1 THEN 100 + WHEN `OrderID` = 2 THEN 200 + ELSE `Qty` + END, + `Note` = CASE + WHEN `OrderID` = 1 THEN Cast('a' as char(1)) + WHEN `OrderID` = 2 THEN Cast('b' as char(1)) + ELSE `Note` + END +WHERE (`OrderID` = 1) + OR (`OrderID` = 2) +[複合主キー] +- SQLServer +UPDATE Orders SET [Qty] = 100, [Note] = Convert(nvarchar(1), 'a') WHERE [OrderID] = 1 AND [ProductID] = 10 +UPDATE Orders SET [Qty] = 200, [Note] = Convert(nvarchar(1), 'b') WHERE [OrderID] = 2 AND [ProductID] = 20 +- Oracle +UPDATE Orders SET "Qty" = 100, "Note" = CAST('a' AS varchar2(1)) WHERE "OrderID" = 1 AND "ProductID" = 10 +UPDATE Orders SET "Qty" = 200, "Note" = CAST('b' AS varchar2(1)) WHERE "OrderID" = 2 AND "ProductID" = 20 +- PstGrS +UPDATE Orders SET "Qty" = CASE + WHEN "OrderID" = 1 AND "ProductID" = 10 THEN 100 + WHEN "OrderID" = 2 AND "ProductID" = 20 THEN 200 + ELSE "Qty" + END, + "Note" = CASE + WHEN "OrderID" = 1 AND "ProductID" = 10 THEN Cast('a' as text) + WHEN "OrderID" = 2 AND "ProductID" = 20 THEN Cast('b' as text) + ELSE "Note" + END +WHERE ("OrderID" = 1 AND "ProductID" = 10) + OR ("OrderID" = 2 AND "ProductID" = 20) +- MySQL +UPDATE Orders SET `Qty` = CASE + WHEN `OrderID` = 1 AND `ProductID` = 10 THEN 100 + WHEN `OrderID` = 2 AND `ProductID` = 20 THEN 200 + ELSE `Qty` + END, + `Note` = CASE + WHEN `OrderID` = 1 AND `ProductID` = 10 THEN Cast('a' as char(1)) + WHEN `OrderID` = 2 AND `ProductID` = 20 THEN Cast('b' as char(1)) + ELSE `Note` + END +WHERE (`OrderID` = 1 AND `ProductID` = 10) + OR (`OrderID` = 2 AND `ProductID` = 20) +[更新対象列なし] +- SQLServer +(生成なし) +- Oracle +(生成なし) +- PstGrS +(生成なし) +- MySQL +(生成なし) +[主キーなし] +- SQLServer +(生成なし) +- Oracle +(生成なし) +- PstGrS +(生成なし) +- MySQL +(生成なし) +---------------------------------------------------------------------------------------------------- +SQLUtility.GetInsertSQLParts +- SQLServer +([OrderID], [ProductID], [Qty], [Note]) +(1, 10, 100, Convert(nvarchar(1), 'a')) +(2, 20, 200, Convert(nvarchar(1), 'b')) +- Oracle +("OrderID", "ProductID", "Qty", "Note") +(1, 10, 100, CAST('a' AS varchar2(1))) +(2, 20, 200, CAST('b' AS varchar2(1))) +- PstGrS +("OrderID", "ProductID", "Qty", "Note") +(1, 10, 100, Cast('a' as text)) +(2, 20, 200, Cast('b' as text)) +- MySQL +(`OrderID`, `ProductID`, `Qty`, `Note`) +(1, 10, 100, Cast('a' as char(1))) +(2, 20, 200, Cast('b' as char(1))) +---------------------------------------------------------------------------------------------------- log4net: Shutdown called on Hierarchy [log4net-default-repository] diff --git a/root/programs/CS/Frameworks/Tests/TestCode/ResultCore100.txt b/root/programs/CS/Frameworks/Tests/TestCode/ResultCore100.txt index f223484f4..357593166 100644 --- a/root/programs/CS/Frameworks/Tests/TestCode/ResultCore100.txt +++ b/root/programs/CS/Frameworks/Tests/TestCode/ResultCore100.txt @@ -1,2323 +1,2427 @@ ----------------------------------------------------------------------------------------------------- -log4net: Configuration update mode [Merge]. -log4net: Retrieving an instance of log4net.Repository.Logger for logger [ACCESS]. -log4net: Setting [ACCESS] additivity to [True]. -log4net: Logger [ACCESS] Level string is [All]. -log4net: Logger [ACCESS] level set to [name="ALL",value=-2147483648]. -log4net: Loading Appender [ACCESS2] type: [log4net.Appender.ConsoleAppender] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] -log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] -log4net: Setting Property [LevelMin] to Level value [DEBUG] -log4net: Setting Property [LevelMax] to Level value [FATAL] -log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] -log4net: Created Appender [ACCESS2] -log4net: Adding appender named [ACCESS2] to logger [ACCESS]. -log4net: Retrieving an instance of log4net.Repository.Logger for logger [SQLTRACE]. -log4net: Setting [SQLTRACE] additivity to [True]. -log4net: Logger [SQLTRACE] Level string is [All]. -log4net: Logger [SQLTRACE] level set to [name="ALL",value=-2147483648]. -log4net: Loading Appender [SQLTRACE2] type: [log4net.Appender.ConsoleAppender] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] -log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] -log4net: Setting Property [LevelMin] to Level value [DEBUG] -log4net: Setting Property [LevelMax] to Level value [FATAL] -log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] -log4net: Created Appender [SQLTRACE2] -log4net: Adding appender named [SQLTRACE2] to logger [SQLTRACE]. -log4net: Retrieving an instance of log4net.Repository.Logger for logger [OPERATION]. -log4net: Setting [OPERATION] additivity to [True]. -log4net: Logger [OPERATION] Level string is [All]. -log4net: Logger [OPERATION] level set to [name="ALL",value=-2147483648]. -log4net: Loading Appender [OPERATION2] type: [log4net.Appender.ConsoleAppender] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] -log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] -log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] -log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] -log4net: Setting Property [LevelMin] to Level value [DEBUG] -log4net: Setting Property [LevelMax] to Level value [FATAL] -log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] -log4net: Created Appender [OPERATION2] -log4net: Adding appender named [OPERATION2] to logger [OPERATION]. -log4net: Hierarchy Threshold [] -[2025/11/18 04:03:14,431],[DEBUG],[2],LogIF.DebugLog("ACCESS"); -[2025/11/18 04:03:14,445],[INFO ],[2],LogIF.InfoLog("ACCESS"); -[2025/11/18 04:03:14,445],[WARN ],[2],LogIF.WarnLog("ACCESS"); -[2025/11/18 04:03:14,446],[ERROR],[2],LogIF.ErrorLog("ACCESS"); -[2025/11/18 04:03:14,446],[FATAL],[2],LogIF.FatalLog("ACCESS"); ----------------------------------------------------------------------------------------------------- -GetMessage: ~メッセージID:I0001に対応する記述(正常系)~ -GetMessage: ~メッセージID:E0001に対応する記述(異常系)~ --------------------------------------------------- -GetSharedProperty: てすと1 -GetSharedProperty: てすと3 ----------------------------------------------------------------------------------------------------- -StringChecker.IsNumbers - あああ: False -StringChecker.IsNumbers - 111: True -StringChecker.IsNumbers_Hankaku - あああ: False -StringChecker.IsNumbers_Hankaku - 111111: True -StringChecker.IsNumbers_Zenkaku - あああ: False -StringChecker.IsNumbers_Zenkaku - 111: True ----------------------------------------------------------------------------------------------------- -StringChecker.IsAlphabet - あああ: False -StringChecker.IsAlphabet - aaa: True -StringChecker.IsAlphabet_Hankaku - あああ: False -StringChecker.IsAlphabet_Hankaku - aaaaaa: True -StringChecker.IsAlphabet_Zenkaku - あああ: False -StringChecker.IsAlphabet_Zenkaku - aaa: True ----------------------------------------------------------------------------------------------------- -StringChecker.IsHiragana - aaa: False -StringChecker.IsHiragana - あああ: True ----------------------------------------------------------------------------------------------------- -StringChecker.IsKatakana - あああ: False -StringChecker.IsKatakana - アアア: True -StringChecker.IsKatakana_Zenkaku - あああ: False -StringChecker.IsKatakana_Zenkaku - アアア: True -StringChecker.IsKatakana_Zenkaku - アアア: False -StringChecker.IsKatakana_Zenkaku - アアアアアア: True ----------------------------------------------------------------------------------------------------- -StringChecker.IsKanji - あああ: False -StringChecker.IsKanji - 亜亜亜: True ----------------------------------------------------------------------------------------------------- -StringChecker.IsShift_Jis - 鱓鱓鱓: False -StringChecker.IsShift_Jis - 亜亜亜: True -StringChecker.IsShift_Jis_Zenkaku - aaaaaa: False -StringChecker.IsShift_Jis_Zenkaku - 亜亜亜: True -StringChecker.IsShift_Jis_Hankaku - aaa: False -StringChecker.IsShift_Jis_Hankaku - aaaaaa: True ----------------------------------------------------------------------------------------------------- -TestFormatChecker.IsJpZipCode -JpZipCode_Hyphen -000-0000: True -aaa-aaaa: False -0000-00000: False -0000-0000: False -000-00000: False -00-000: False -00-0000: False -000-000: False -JpZipKuCode1_Hyphen -000-00: True -aaa-aa: False -0000-000: False -0000-00: False -000-000: False -00-0: False -00-00: False -000-0: False -JpZipKuCode2_Hyphen -000: True -aaa: False -0000: False -00: False -JpZipCode_NoHyphen -0000000: True -aaaaaaa: False -00000000: False -000000: False -JpZipKuCode1_NoHyphen -00000: True -aaaaa: False -000000: False -0000: False -JpZipKuCode2_NoHyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode_Hyphen -JpZipCode_Hyphen -000-0000: True -aaa-aaaa: False -0000-00000: False -0000-0000: False -000-00000: False -00-000: False -00-0000: False -000-000: False -JpZipKuCode1_Hyphen -000-00: True -aaa-aa: False -0000-000: False -0000-00: False -000-000: False -00-0: False -00-00: False -000-0: False -JpZipKuCode2_Hyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode_NoHyphen -JpZipCode_NoHyphen -0000000: True -aaaaaaa: False -00000000: False -000000: False -JpZipKuCode1_NoHyphen -00000: True -aaaaa: False -000000: False -0000: False -JpZipKuCode2_NoHyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode7 -JpZipCode_Hyphen -000-0000: True -aaa-aaaa: False -0000-00000: False -0000-0000: False -000-00000: False -00-000: False -00-0000: False -000-000: False -JpZipCode_NoHyphen -0000000: True -aaaaaaa: False -00000000: False -000000: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode7_Hyphen -JpZipCode_Hyphen -000-0000: True -aaa-aaaa: False -0000-00000: False -0000-0000: False -000-00000: False -00-000: False -00-0000: False -000-000: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode7_NoHyphen -JpZipCode_NoHyphen -0000000: True -aaaaaaa: False -00000000: False -000000: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode5 -JpZipKuCode1_Hyphen -000-00: True -aaa-aa: False -0000-000: False -0000-00: False -000-000: False -00-0: False -00-00: False -000-0: False -JpZipKuCode2_Hyphen -000: True -aaa: False -0000: False -00: False -JpZipKuCode1_NoHyphen -00000: True -aaaaa: False -000000: False -0000: False -JpZipKuCode2_NoHyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode5_Hyphen -JpZipKuCode1_Hyphen -000-00: True -aaa-aa: False -0000-000: False -0000-00: False -000-000: False -00-0: False -00-00: False -000-0: False -JpZipKuCode2_Hyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpZipCode5_NoHyphen -JpZipKuCode1_NoHyphen -00000: True -aaaaa: False -000000: False -0000: False -JpZipKuCode2_NoHyphen -000: True -aaa: False -0000: False -00: False --------------------------------------------------- -TestFormatChecker.IsJpTelephoneNumber -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: True -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: True -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: True -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: True -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: True -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: True -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: True -020-999-9999: True -020-9999-999: False -060-9999-9999: True -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: True -060-999-9999: True -060-9999-999: False -070-9999-9999: True -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: True -070-999-9999: True -070-9999-999: False -080-9999-9999: True -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: True -080-999-9999: True -080-9999-999: False -090-9999-9999: True -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: True -090-999-9999: True -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: True -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: True -06099999999: True -07099999999: True -08099999999: True -09099999999: True -01099999999: False -03099999999: False -04099999999: False -05099999999: True -JpIpPhoneNumber_Hyphen -050-9999-9999: True -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: True -050-999-9999: True -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: True -030-9999-9999: False -040-9999-9999: False -060-9999-9999: True -070-9999-9999: True -080-9999-9999: True -090-9999-9999: True -JpIpPhoneNumber_NoHyphen -05099999999: True -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: True -01099999999: False -02099999999: True -03099999999: False -04099999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True --------------------------------------------------- -TestFormatChecker.IsJpTelephoneNumber_Hyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: True -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: True -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: True -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: True -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: True -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: True -020-999-9999: True -020-9999-999: False -060-9999-9999: True -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: True -060-999-9999: True -060-9999-999: False -070-9999-9999: True -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: True -070-999-9999: True -070-9999-999: False -080-9999-9999: True -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: True -080-999-9999: True -080-9999-999: False -090-9999-9999: True -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: True -090-999-9999: True -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: True -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: True -050-999-9999: True -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: True -030-9999-9999: False -040-9999-9999: False -060-9999-9999: True -070-9999-9999: True -080-9999-9999: True -090-9999-9999: True -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpTelephoneNumber_NoHyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: True -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: True -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: True -06099999999: True -07099999999: True -08099999999: True -09099999999: True -01099999999: False -03099999999: False -04099999999: False -05099999999: True -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: True -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: True -01099999999: False -02099999999: True -03099999999: False -04099999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True --------------------------------------------------- -TestFormatChecker.IsJpFixedLinePhoneNumber -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: True -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: True -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: True -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: True -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: True -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: True -020-999-9999: True -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: True -060-999-9999: True -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: True -070-999-9999: True -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: True -080-999-9999: True -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: True -090-999-9999: True -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: True -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: True -050-999-9999: True -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: True -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpFixedLinePhoneNumber_Hyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: True -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: True -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: True -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: True -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: True -020-999-9999: True -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: True -060-999-9999: True -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: True -070-999-9999: True -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: True -080-999-9999: True -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: True -090-999-9999: True -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: True -050-999-9999: True -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpFixedLinePhoneNumber_NoHyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: True -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: True -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: True -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpCellularPhoneNumber -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: True -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: True -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: True -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: True -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: True -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: True -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: True -030-9999-9999: False -040-9999-9999: False -060-9999-9999: True -070-9999-9999: True -080-9999-9999: True -090-9999-9999: True -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: True -03099999999: False -04099999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True --------------------------------------------------- -TestFormatChecker.IsJpCellularPhoneNumber_Hyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: True -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: True -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: True -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: True -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: True -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: True -030-9999-9999: False -040-9999-9999: False -060-9999-9999: True -070-9999-9999: True -080-9999-9999: True -090-9999-9999: True -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpCellularPhoneNumber_NoHyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: True -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: True -03099999999: False -04099999999: False -06099999999: True -07099999999: True -08099999999: True -09099999999: True --------------------------------------------------- -TestFormatChecker.IsJpIpPhoneNumber -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: True -JpIpPhoneNumber_Hyphen -050-9999-9999: True -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: True -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpIpPhoneNumber_Hyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: False -JpIpPhoneNumber_Hyphen -050-9999-9999: True -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: False -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False --------------------------------------------------- -TestFormatChecker.IsJpIpPhoneNumber_NoHyphen -JpFixedLinePhoneNumber_Hyphen -09999-9-9999: False -99999-9-9999: False -0aaaa-a-aaaa: False -099999-9-9999: False -09999-99-9999: False -09999-9-99999: False -0999--999: False -0999-9-9999: False -09999--9999: False -09999-9-999: False -0999-99-9999: False -9999-99-9999: False -0aaa-aa-aaaa: False -09999-999-99999: False -09999-99-9999: False -0999-999-9999: False -0999-99-99999: False -099-9-999: False -099-99-9999: False -0999-9-9999: False -0999-99-999: False -099-999-9999: False -999-999-9999: False -0aa-aaa-aaaa: False -0999-9999-99999: False -0999-999-9999: False -099-9999-9999: False -099-999-99999: False -09-99-999: False -09-999-9999: False -099-99-9999: False -099-999-999: False -09-9999-9999: False -99-9999-9999: False -0a-aaaa-aaaa: False -099-99999-99999: False -099-9999-9999: False -09-99999-9999: False -09-9999-99999: False -0-999-999: False -0-9999-9999: False -09-999-9999: False -09-9999-999: False -JpFixedLinePhoneNumber_NoHyphen -0999999999: False -9999999999: False -0aaaaaaaaa: False -09999999999: False -099999999: False -JpCellularPhoneNumber_Hyphen -020-9999-9999: False -929-9999-9999: False -020-aaaa-aaaa: False -0209-99999-99999: False -0209-9999-9999: False -020-99999-9999: False -020-9999-99999: False -02-999-999: False -02-9999-9999: False -020-999-9999: False -020-9999-999: False -060-9999-9999: False -969-9999-9999: False -060-aaaa-aaaa: False -0609-99999-99999: False -0609-9999-9999: False -060-99999-9999: False -060-9999-99999: False -06-999-999: False -06-9999-9999: False -060-999-9999: False -060-9999-999: False -070-9999-9999: False -979-9999-9999: False -070-aaaa-aaaa: False -0709-99999-99999: False -0709-9999-9999: False -070-99999-9999: False -070-9999-99999: False -07-999-999: False -07-9999-9999: False -070-999-9999: False -070-9999-999: False -080-9999-9999: False -989-9999-9999: False -080-aaaa-aaaa: False -0809-99999-99999: False -0809-9999-9999: False -080-99999-9999: False -080-9999-99999: False -08-999-999: False -08-9999-9999: False -080-999-9999: False -080-9999-999: False -090-9999-9999: False -999-9999-9999: False -090-aaaa-aaaa: False -0909-99999-99999: False -0909-9999-9999: False -090-99999-9999: False -090-9999-99999: False -09-999-999: False -09-9999-9999: False -090-999-9999: False -090-9999-999: False -JpCellularPhoneNumber_NoHyphen -02099999999: False -92999999999: False -020aaaaaaaa: False -020999999999: False -0209999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False -01099999999: False -03099999999: False -04099999999: False -05099999999: True -JpIpPhoneNumber_Hyphen -050-9999-9999: False -959-9999-9999: False -050-aaaa-aaaa: False -0509-99999-99999: False -0509-9999-9999: False -050-99999-9999: False -050-9999-99999: False -05-999-999: False -05-9999-9999: False -050-999-9999: False -050-9999-999: False -9999999999999: False -010-9999-9999: False -020-9999-9999: False -030-9999-9999: False -040-9999-9999: False -060-9999-9999: False -070-9999-9999: False -080-9999-9999: False -090-9999-9999: False -JpIpPhoneNumber_NoHyphen -05099999999: True -95999999999: False -050aaaaaaaa: False -050999999999: False -0509999999: False -01099999999: False -02099999999: False -03099999999: False -04099999999: False -06099999999: False -07099999999: False -08099999999: False -09099999999: False ----------------------------------------------------------------------------------------------------- -StringConverter.ToHankaku - アアア: アアア -StringConverter.ToZenkaku - アアア: アアア -StringConverter.ToHiragana - アアア: あああ -StringConverter.ToKatakana - あああ: アアア ----------------------------------------------------------------------------------------------------- -FormatConverter.SeirekiToWareki -1977/4/24, ggy年M月d日(ddd): 昭和52年4月24日(日) -1977/4/24, ggy年M月d日(ddd)H:m:s: 昭和52年4月24日(日)0:0:0 -1977/4/24 19:15:12, ggy年M月d日(ddd): 昭和52年4月24日(日) -1977/4/24 19:15:12, ggy年M月d日(ddd)H:m:s: 昭和52年4月24日(日)19:15:12 -1977/4/24 19:15:12, ggy年M月d日(ddd)tt h:m:s: 昭和52年4月24日(日)午後 7:15:12 -1992/2/6 1:1:1, ggyy年MM月dd日 dddd HH:mm:ss: 平成04年02月06日 木曜日 01:01:01 -1992/2/6 13:1:1, ggyy年MM月dd日 dddd tt hh:mm:ss: 平成04年02月06日 木曜日 午後 01:01:01 --------------------------------------------------- -FormatConverter.WarekiToSeireki -昭和52年4月24日(日), ggy年M月d日(ddd): 1977/04/24 0:00:00 -昭和52年4月24日(日)19:15:12, ggy年M月d日(ddd)H:m:s: 1977/04/24 19:15:12 -昭和52年4月24日(日)午後 7:15:12, ggy年M月d日(ddd)tt h:m:s: 1977/04/24 19:15:12 -平成04年02月06日 木曜日 01:01:01, ggyy年MM月dd日 dddd HH:mm:ss: 1992/02/06 1:01:01 -平成04年02月06日 木曜日 午後 01:01:01, ggyy年MM月dd日 dddd tt hh:mm:ss: 1992/02/06 13:01:01 --------------------------------------------------- -FormatConverter.AddFigure3 -12,345 -123,456,789 -123.45 -12,345.6789 --12,345 --123,456,789 --123.45 --12,345.6789 -12,345 -123,456,789 -123.45 -12,345.6789 --12,345 --123,456,789 --123.45 --12,345.6789 ----------------------------------------------------------------------------------------------------- -FormatConverter.AddFigure4 -1,2345 -1,2345,6789 -123.45 -1,2345.6789 --1,2345 --1,2345,6789 --123.45 --1,2345.6789 -1,2345 -1,2345,6789 -123.45 -1,2345.6789 --1,2345 --1,2345,6789 --123.45 --1,2345.6789 ----------------------------------------------------------------------------------------------------- -FormatConverter.Suppress -"", 10, '@': @@@@@@@@@@ -"123456789", 0, '@': 123456789 -"123456789", 1, '@': 123456789 -"123456789", 5, '@': 123456789 -"123456789", 9, '@': 123456789 -"123456789", 10, '@': @123456789 -"123456789", 11, '@': @@123456789 -"123456789", 20, '@': @@@@@@@@@@@123456789 -"", 10, '@': @@@@@@@@@@ -"123456789", 0, '@': abcdefg -"123456789", 1, '@': abcdefg -"123456789", 5, '@': abcdefg -"123456789", 9, '@': @@abcdefg -"123456789", 10, '@': @@@abcdefg -"123456789", 11, '@': @@@@abcdefg -"123456789", 20, '@': @@@@@@@@@@@@@abcdefg ----------------------------------------------------------------------------------------------------- -CustomEncode.HtmlEncode: " id="txtXXXXX" /><script type="text/javascript">alert("XSS!!!")</script><input name="txtXXXXX" type="text" value=" ----------------------------------------------------------------------------------------------------- -CustomEncode.UrlEncode: http://www.google.co.jp/search?hl=ja&q=%26 -CustomEncode.UrlEncode2: http%3A%2F%2Fwww.google.co.jp%2Fsearch%3Fhl%3Dja%26q%3D%26 -CustomEncode.UrlEncode2: http%3A%2F%2Fwww.google.co.jp%2Fsearch%3Fhl%3Dja%26q%3D%3C%3E ----------------------------------------------------------------------------------------------------- +---------------------------------------------------------------------------------------------------- +log4net: Configuration update mode [Merge]. +log4net: Retrieving an instance of log4net.Repository.Logger for logger [ACCESS]. +log4net: Setting [ACCESS] additivity to [True]. +log4net: Logger [ACCESS] Level string is [All]. +log4net: Logger [ACCESS] level set to [name="ALL",value=-2147483648]. +log4net: Loading Appender [ACCESS2] type: [log4net.Appender.ConsoleAppender] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] +log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] +log4net: Setting Property [LevelMin] to Level value [DEBUG] +log4net: Setting Property [LevelMax] to Level value [FATAL] +log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] +log4net: Created Appender [ACCESS2] +log4net: Adding appender named [ACCESS2] to logger [ACCESS]. +log4net: Retrieving an instance of log4net.Repository.Logger for logger [SQLTRACE]. +log4net: Setting [SQLTRACE] additivity to [True]. +log4net: Logger [SQLTRACE] Level string is [All]. +log4net: Logger [SQLTRACE] level set to [name="ALL",value=-2147483648]. +log4net: Loading Appender [SQLTRACE2] type: [log4net.Appender.ConsoleAppender] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] +log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] +log4net: Setting Property [LevelMin] to Level value [DEBUG] +log4net: Setting Property [LevelMax] to Level value [FATAL] +log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] +log4net: Created Appender [SQLTRACE2] +log4net: Adding appender named [SQLTRACE2] to logger [SQLTRACE]. +log4net: Retrieving an instance of log4net.Repository.Logger for logger [OPERATION]. +log4net: Setting [OPERATION] additivity to [True]. +log4net: Logger [OPERATION] Level string is [All]. +log4net: Logger [OPERATION] level set to [name="ALL",value=-2147483648]. +log4net: Loading Appender [OPERATION2] type: [log4net.Appender.ConsoleAppender] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [ConversionPattern] to String value [[%date{yyyy/MM/dd HH:mm:ss,fff}],[%-5level],[%thread],%message%newline] +log4net: Converter [literal] Option [[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [date] Option [yyyy/MM/dd HH:mm:ss,fff] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [level] Option [] Format [min=5,max=2147483647,leftAlign=True] +log4net: Converter [literal] Option [],[] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [thread] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [literal] Option [],] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [message] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Converter [newline] Option [] Format [min=-1,max=2147483647,leftAlign=False] +log4net: Setting Property [Layout] to object [log4net.Layout.PatternLayout] +log4net: Setting Property [LevelMin] to Level value [DEBUG] +log4net: Setting Property [LevelMax] to Level value [FATAL] +log4net: Setting Collection Property [AddFilter] to object [log4net.Filter.LevelRangeFilter] +log4net: Created Appender [OPERATION2] +log4net: Adding appender named [OPERATION2] to logger [OPERATION]. +log4net: Hierarchy Threshold [] +[2026/08/02 08:44:09,282],[DEBUG],[2],LogIF.DebugLog("ACCESS"); +[2026/08/02 08:44:09,302],[INFO ],[2],LogIF.InfoLog("ACCESS"); +[2026/08/02 08:44:09,303],[WARN ],[2],LogIF.WarnLog("ACCESS"); +[2026/08/02 08:44:09,305],[ERROR],[2],LogIF.ErrorLog("ACCESS"); +[2026/08/02 08:44:09,306],[FATAL],[2],LogIF.FatalLog("ACCESS"); +---------------------------------------------------------------------------------------------------- +GetMessage: ~メッセージID:I0001に対応する記述(正常系)~ +GetMessage: ~メッセージID:E0001に対応する記述(異常系)~ +-------------------------------------------------- +GetSharedProperty: てすと1 +GetSharedProperty: てすと3 +---------------------------------------------------------------------------------------------------- +StringChecker.IsNumbers - あああ: False +StringChecker.IsNumbers - 111: True +StringChecker.IsNumbers_Hankaku - あああ: False +StringChecker.IsNumbers_Hankaku - 111111: True +StringChecker.IsNumbers_Zenkaku - あああ: False +StringChecker.IsNumbers_Zenkaku - 111: True +---------------------------------------------------------------------------------------------------- +StringChecker.IsAlphabet - あああ: False +StringChecker.IsAlphabet - aaa: True +StringChecker.IsAlphabet_Hankaku - あああ: False +StringChecker.IsAlphabet_Hankaku - aaaaaa: True +StringChecker.IsAlphabet_Zenkaku - あああ: False +StringChecker.IsAlphabet_Zenkaku - aaa: True +---------------------------------------------------------------------------------------------------- +StringChecker.IsHiragana - aaa: False +StringChecker.IsHiragana - あああ: True +---------------------------------------------------------------------------------------------------- +StringChecker.IsKatakana - あああ: False +StringChecker.IsKatakana - アアア: True +StringChecker.IsKatakana_Zenkaku - あああ: False +StringChecker.IsKatakana_Zenkaku - アアア: True +StringChecker.IsKatakana_Zenkaku - アアア: False +StringChecker.IsKatakana_Zenkaku - アアアアアア: True +---------------------------------------------------------------------------------------------------- +StringChecker.IsKanji - あああ: False +StringChecker.IsKanji - 亜亜亜: True +---------------------------------------------------------------------------------------------------- +StringChecker.IsShift_Jis - 鱓鱓鱓: False +StringChecker.IsShift_Jis - 亜亜亜: True +StringChecker.IsShift_Jis_Zenkaku - aaaaaa: False +StringChecker.IsShift_Jis_Zenkaku - 亜亜亜: True +StringChecker.IsShift_Jis_Hankaku - aaa: False +StringChecker.IsShift_Jis_Hankaku - aaaaaa: True +---------------------------------------------------------------------------------------------------- +TestFormatChecker.IsJpZipCode +JpZipCode_Hyphen +000-0000: True +aaa-aaaa: False +0000-00000: False +0000-0000: False +000-00000: False +00-000: False +00-0000: False +000-000: False +JpZipKuCode1_Hyphen +000-00: True +aaa-aa: False +0000-000: False +0000-00: False +000-000: False +00-0: False +00-00: False +000-0: False +JpZipKuCode2_Hyphen +000: True +aaa: False +0000: False +00: False +JpZipCode_NoHyphen +0000000: True +aaaaaaa: False +00000000: False +000000: False +JpZipKuCode1_NoHyphen +00000: True +aaaaa: False +000000: False +0000: False +JpZipKuCode2_NoHyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode_Hyphen +JpZipCode_Hyphen +000-0000: True +aaa-aaaa: False +0000-00000: False +0000-0000: False +000-00000: False +00-000: False +00-0000: False +000-000: False +JpZipKuCode1_Hyphen +000-00: True +aaa-aa: False +0000-000: False +0000-00: False +000-000: False +00-0: False +00-00: False +000-0: False +JpZipKuCode2_Hyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode_NoHyphen +JpZipCode_NoHyphen +0000000: True +aaaaaaa: False +00000000: False +000000: False +JpZipKuCode1_NoHyphen +00000: True +aaaaa: False +000000: False +0000: False +JpZipKuCode2_NoHyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode7 +JpZipCode_Hyphen +000-0000: True +aaa-aaaa: False +0000-00000: False +0000-0000: False +000-00000: False +00-000: False +00-0000: False +000-000: False +JpZipCode_NoHyphen +0000000: True +aaaaaaa: False +00000000: False +000000: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode7_Hyphen +JpZipCode_Hyphen +000-0000: True +aaa-aaaa: False +0000-00000: False +0000-0000: False +000-00000: False +00-000: False +00-0000: False +000-000: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode7_NoHyphen +JpZipCode_NoHyphen +0000000: True +aaaaaaa: False +00000000: False +000000: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode5 +JpZipKuCode1_Hyphen +000-00: True +aaa-aa: False +0000-000: False +0000-00: False +000-000: False +00-0: False +00-00: False +000-0: False +JpZipKuCode2_Hyphen +000: True +aaa: False +0000: False +00: False +JpZipKuCode1_NoHyphen +00000: True +aaaaa: False +000000: False +0000: False +JpZipKuCode2_NoHyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode5_Hyphen +JpZipKuCode1_Hyphen +000-00: True +aaa-aa: False +0000-000: False +0000-00: False +000-000: False +00-0: False +00-00: False +000-0: False +JpZipKuCode2_Hyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpZipCode5_NoHyphen +JpZipKuCode1_NoHyphen +00000: True +aaaaa: False +000000: False +0000: False +JpZipKuCode2_NoHyphen +000: True +aaa: False +0000: False +00: False +-------------------------------------------------- +TestFormatChecker.IsJpTelephoneNumber +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: True +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: True +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: True +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: True +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: True +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: True +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: True +020-999-9999: True +020-9999-999: False +060-9999-9999: True +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: True +060-999-9999: True +060-9999-999: False +070-9999-9999: True +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: True +070-999-9999: True +070-9999-999: False +080-9999-9999: True +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: True +080-999-9999: True +080-9999-999: False +090-9999-9999: True +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: True +090-999-9999: True +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: True +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: True +06099999999: True +07099999999: True +08099999999: True +09099999999: True +01099999999: False +03099999999: False +04099999999: False +05099999999: True +JpIpPhoneNumber_Hyphen +050-9999-9999: True +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: True +050-999-9999: True +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: True +030-9999-9999: False +040-9999-9999: False +060-9999-9999: True +070-9999-9999: True +080-9999-9999: True +090-9999-9999: True +JpIpPhoneNumber_NoHyphen +05099999999: True +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: True +01099999999: False +02099999999: True +03099999999: False +04099999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +-------------------------------------------------- +TestFormatChecker.IsJpTelephoneNumber_Hyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: True +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: True +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: True +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: True +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: True +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: True +020-999-9999: True +020-9999-999: False +060-9999-9999: True +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: True +060-999-9999: True +060-9999-999: False +070-9999-9999: True +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: True +070-999-9999: True +070-9999-999: False +080-9999-9999: True +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: True +080-999-9999: True +080-9999-999: False +090-9999-9999: True +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: True +090-999-9999: True +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: True +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: True +050-999-9999: True +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: True +030-9999-9999: False +040-9999-9999: False +060-9999-9999: True +070-9999-9999: True +080-9999-9999: True +090-9999-9999: True +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpTelephoneNumber_NoHyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: True +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: True +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: True +06099999999: True +07099999999: True +08099999999: True +09099999999: True +01099999999: False +03099999999: False +04099999999: False +05099999999: True +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: True +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: True +01099999999: False +02099999999: True +03099999999: False +04099999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +-------------------------------------------------- +TestFormatChecker.IsJpFixedLinePhoneNumber +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: True +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: True +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: True +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: True +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: True +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: True +020-999-9999: True +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: True +060-999-9999: True +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: True +070-999-9999: True +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: True +080-999-9999: True +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: True +090-999-9999: True +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: True +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: True +050-999-9999: True +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: True +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpFixedLinePhoneNumber_Hyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: True +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: True +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: True +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: True +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: True +020-999-9999: True +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: True +060-999-9999: True +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: True +070-999-9999: True +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: True +080-999-9999: True +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: True +090-999-9999: True +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: True +050-999-9999: True +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpFixedLinePhoneNumber_NoHyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: True +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: True +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: True +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpCellularPhoneNumber +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: True +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: True +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: True +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: True +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: True +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: True +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: True +030-9999-9999: False +040-9999-9999: False +060-9999-9999: True +070-9999-9999: True +080-9999-9999: True +090-9999-9999: True +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: True +03099999999: False +04099999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +-------------------------------------------------- +TestFormatChecker.IsJpCellularPhoneNumber_Hyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: True +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: True +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: True +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: True +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: True +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: True +030-9999-9999: False +040-9999-9999: False +060-9999-9999: True +070-9999-9999: True +080-9999-9999: True +090-9999-9999: True +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpCellularPhoneNumber_NoHyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: True +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: True +03099999999: False +04099999999: False +06099999999: True +07099999999: True +08099999999: True +09099999999: True +-------------------------------------------------- +TestFormatChecker.IsJpIpPhoneNumber +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: True +JpIpPhoneNumber_Hyphen +050-9999-9999: True +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: True +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpIpPhoneNumber_Hyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: False +JpIpPhoneNumber_Hyphen +050-9999-9999: True +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: False +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +-------------------------------------------------- +TestFormatChecker.IsJpIpPhoneNumber_NoHyphen +JpFixedLinePhoneNumber_Hyphen +09999-9-9999: False +99999-9-9999: False +0aaaa-a-aaaa: False +099999-9-9999: False +09999-99-9999: False +09999-9-99999: False +0999--999: False +0999-9-9999: False +09999--9999: False +09999-9-999: False +0999-99-9999: False +9999-99-9999: False +0aaa-aa-aaaa: False +09999-999-99999: False +09999-99-9999: False +0999-999-9999: False +0999-99-99999: False +099-9-999: False +099-99-9999: False +0999-9-9999: False +0999-99-999: False +099-999-9999: False +999-999-9999: False +0aa-aaa-aaaa: False +0999-9999-99999: False +0999-999-9999: False +099-9999-9999: False +099-999-99999: False +09-99-999: False +09-999-9999: False +099-99-9999: False +099-999-999: False +09-9999-9999: False +99-9999-9999: False +0a-aaaa-aaaa: False +099-99999-99999: False +099-9999-9999: False +09-99999-9999: False +09-9999-99999: False +0-999-999: False +0-9999-9999: False +09-999-9999: False +09-9999-999: False +JpFixedLinePhoneNumber_NoHyphen +0999999999: False +9999999999: False +0aaaaaaaaa: False +09999999999: False +099999999: False +JpCellularPhoneNumber_Hyphen +020-9999-9999: False +929-9999-9999: False +020-aaaa-aaaa: False +0209-99999-99999: False +0209-9999-9999: False +020-99999-9999: False +020-9999-99999: False +02-999-999: False +02-9999-9999: False +020-999-9999: False +020-9999-999: False +060-9999-9999: False +969-9999-9999: False +060-aaaa-aaaa: False +0609-99999-99999: False +0609-9999-9999: False +060-99999-9999: False +060-9999-99999: False +06-999-999: False +06-9999-9999: False +060-999-9999: False +060-9999-999: False +070-9999-9999: False +979-9999-9999: False +070-aaaa-aaaa: False +0709-99999-99999: False +0709-9999-9999: False +070-99999-9999: False +070-9999-99999: False +07-999-999: False +07-9999-9999: False +070-999-9999: False +070-9999-999: False +080-9999-9999: False +989-9999-9999: False +080-aaaa-aaaa: False +0809-99999-99999: False +0809-9999-9999: False +080-99999-9999: False +080-9999-99999: False +08-999-999: False +08-9999-9999: False +080-999-9999: False +080-9999-999: False +090-9999-9999: False +999-9999-9999: False +090-aaaa-aaaa: False +0909-99999-99999: False +0909-9999-9999: False +090-99999-9999: False +090-9999-99999: False +09-999-999: False +09-9999-9999: False +090-999-9999: False +090-9999-999: False +JpCellularPhoneNumber_NoHyphen +02099999999: False +92999999999: False +020aaaaaaaa: False +020999999999: False +0209999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +01099999999: False +03099999999: False +04099999999: False +05099999999: True +JpIpPhoneNumber_Hyphen +050-9999-9999: False +959-9999-9999: False +050-aaaa-aaaa: False +0509-99999-99999: False +0509-9999-9999: False +050-99999-9999: False +050-9999-99999: False +05-999-999: False +05-9999-9999: False +050-999-9999: False +050-9999-999: False +9999999999999: False +010-9999-9999: False +020-9999-9999: False +030-9999-9999: False +040-9999-9999: False +060-9999-9999: False +070-9999-9999: False +080-9999-9999: False +090-9999-9999: False +JpIpPhoneNumber_NoHyphen +05099999999: True +95999999999: False +050aaaaaaaa: False +050999999999: False +0509999999: False +01099999999: False +02099999999: False +03099999999: False +04099999999: False +06099999999: False +07099999999: False +08099999999: False +09099999999: False +---------------------------------------------------------------------------------------------------- +StringConverter.ToHankaku - アアア: アアア +StringConverter.ToZenkaku - アアア: アアア +StringConverter.ToHiragana - アアア: あああ +StringConverter.ToKatakana - あああ: アアア +---------------------------------------------------------------------------------------------------- +FormatConverter.SeirekiToWareki +1977/4/24, ggy年M月d日(ddd): 昭和52年4月24日(日) +1977/4/24, ggy年M月d日(ddd)H:m:s: 昭和52年4月24日(日)0:0:0 +1977/4/24 19:15:12, ggy年M月d日(ddd): 昭和52年4月24日(日) +1977/4/24 19:15:12, ggy年M月d日(ddd)H:m:s: 昭和52年4月24日(日)19:15:12 +1977/4/24 19:15:12, ggy年M月d日(ddd)tt h:m:s: 昭和52年4月24日(日)午後 7:15:12 +1992/2/6 1:1:1, ggyy年MM月dd日 dddd HH:mm:ss: 平成04年02月06日 木曜日 01:01:01 +1992/2/6 13:1:1, ggyy年MM月dd日 dddd tt hh:mm:ss: 平成04年02月06日 木曜日 午後 01:01:01 +-------------------------------------------------- +FormatConverter.WarekiToSeireki +昭和52年4月24日(日), ggy年M月d日(ddd): 1977/04/24 0:00:00 +昭和52年4月24日(日)19:15:12, ggy年M月d日(ddd)H:m:s: 1977/04/24 19:15:12 +昭和52年4月24日(日)午後 7:15:12, ggy年M月d日(ddd)tt h:m:s: 1977/04/24 19:15:12 +平成04年02月06日 木曜日 01:01:01, ggyy年MM月dd日 dddd HH:mm:ss: 1992/02/06 1:01:01 +平成04年02月06日 木曜日 午後 01:01:01, ggyy年MM月dd日 dddd tt hh:mm:ss: 1992/02/06 13:01:01 +-------------------------------------------------- +FormatConverter.AddFigure3 +12,345 +123,456,789 +123.45 +12,345.6789 +-12,345 +-123,456,789 +-123.45 +-12,345.6789 +12,345 +123,456,789 +123.45 +12,345.6789 +-12,345 +-123,456,789 +-123.45 +-12,345.6789 +---------------------------------------------------------------------------------------------------- +FormatConverter.AddFigure4 +1,2345 +1,2345,6789 +123.45 +1,2345.6789 +-1,2345 +-1,2345,6789 +-123.45 +-1,2345.6789 +1,2345 +1,2345,6789 +123.45 +1,2345.6789 +-1,2345 +-1,2345,6789 +-123.45 +-1,2345.6789 +---------------------------------------------------------------------------------------------------- +FormatConverter.Suppress +"", 10, '@': @@@@@@@@@@ +"123456789", 0, '@': 123456789 +"123456789", 1, '@': 123456789 +"123456789", 5, '@': 123456789 +"123456789", 9, '@': 123456789 +"123456789", 10, '@': @123456789 +"123456789", 11, '@': @@123456789 +"123456789", 20, '@': @@@@@@@@@@@123456789 +"", 10, '@': @@@@@@@@@@ +"123456789", 0, '@': abcdefg +"123456789", 1, '@': abcdefg +"123456789", 5, '@': abcdefg +"123456789", 9, '@': @@abcdefg +"123456789", 10, '@': @@@abcdefg +"123456789", 11, '@': @@@@abcdefg +"123456789", 20, '@': @@@@@@@@@@@@@abcdefg +---------------------------------------------------------------------------------------------------- +CustomEncode.HtmlEncode: " id="txtXXXXX" /><script type="text/javascript">alert("XSS!!!")</script><input name="txtXXXXX" type="text" value=" +---------------------------------------------------------------------------------------------------- +CustomEncode.UrlEncode: http://www.google.co.jp/search?hl=ja&q=%26 +CustomEncode.UrlEncode2: http%3A%2F%2Fwww.google.co.jp%2Fsearch%3Fhl%3Dja%26q%3D%26 +CustomEncode.UrlEncode2: http%3A%2F%2Fwww.google.co.jp%2Fsearch%3Fhl%3Dja%26q%3D%3C%3E +---------------------------------------------------------------------------------------------------- jis2k4.GetStringInfo - あああ: Char長:3; 文字列長3; バイト長6; - ----------------------------------------------------------------------------------------------------- -jis2k4.CheckSurrogatesPairChar - あああ: False -jis2k4.CheckSurrogatesPairChar - あ𩸽あ: True -jis2k4.CheckSurrogatesPairChar - あああ: -1文字目 -jis2k4.CheckSurrogatesPairChar - あ𩸽あ: 1文字目 ----------------------------------------------------------------------------------------------------- -jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: ああ -jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: あ●あ -jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: あ●あ ----------------------------------------------------------------------------------------------------- -jis2k4.CheckCharAddedWithJIS2k4 - あああ: False -jis2k4.CheckCharAddedWithJIS2k4 - あ噓あ: True -jis2k4.CheckCharAddedWithJIS2k4 - あああ: -1文字目 -jis2k4.CheckCharAddedWithJIS2k4 - あ噓あ: 1文字目 ----------------------------------------------------------------------------------------------------- -jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: ああ -jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: あ●あ -jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: あ●あ ----------------------------------------------------------------------------------------------------- -Friday > Friday -Wednesday > Wednesday -Saturday > Saturday -Friday > Friday -Saturday > Saturday -------------------------- -Friday > Friday -Wednesday > Wednesday -Saturday > Saturday -Friday > Friday -Saturday > Saturday --------------------------------------------------- -V2 > V2 -V3 > V3 -V4 > V4 -------------------------- -V2 > V2 -V3 > V3 -V4 > V4 --------------------------------------------------- -V0 > V0 -V2 > V2 -V4 > V4 -------------------------- -V0 > V0 -V2 > V2 -V4 > V4 --------------------------------------------------- -One > One -One,Two > One,Two -Three > Three -Four > Four -------------------------- -One > One -One,Two > One, Two -Three > Three -Four > Four ----------------------------------------------------------------------------------------------------- -XmlLib > is working properly. ----------------------------------------------------------------------------------------------------- -DeflateCompression(FileStream)-1 > is working properly. -DeflateCompression(FileStream)-2 > is working properly. --------------------------------------------------- -DeflateCompression(MemoryStream) > is working properly. ----------------------------------------------------------------------------------------------------- - log4net: Shutdown called on Hierarchy [log4net-default-repository] + +---------------------------------------------------------------------------------------------------- +jis2k4.CheckSurrogatesPairChar - あああ: False +jis2k4.CheckSurrogatesPairChar - あ𩸽あ: True +jis2k4.CheckSurrogatesPairChar - あああ: -1文字目 +jis2k4.CheckSurrogatesPairChar - あ𩸽あ: 1文字目 +---------------------------------------------------------------------------------------------------- +jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: ああ +jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: あ●あ +jis2k4.DeleteSurrogatesPairChar - あ𩸽あ: あ●あ +---------------------------------------------------------------------------------------------------- +jis2k4.CheckCharAddedWithJIS2k4 - あああ: False +jis2k4.CheckCharAddedWithJIS2k4 - あ噓あ: True +jis2k4.CheckCharAddedWithJIS2k4 - あああ: -1文字目 +jis2k4.CheckCharAddedWithJIS2k4 - あ噓あ: 1文字目 +---------------------------------------------------------------------------------------------------- +jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: ああ +jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: あ●あ +jis2k4.DeleteCharAddedWithJIS2k4 - あ噓あ: あ●あ +---------------------------------------------------------------------------------------------------- +Friday > Friday +Wednesday > Wednesday +Saturday > Saturday +Friday > Friday +Saturday > Saturday +------------------------- +Friday > Friday +Wednesday > Wednesday +Saturday > Saturday +Friday > Friday +Saturday > Saturday +-------------------------------------------------- +V2 > V2 +V3 > V3 +V4 > V4 +------------------------- +V2 > V2 +V3 > V3 +V4 > V4 +-------------------------------------------------- +V0 > V0 +V2 > V2 +V4 > V4 +------------------------- +V0 > V0 +V2 > V2 +V4 > V4 +-------------------------------------------------- +One > One +One,Two > One,Two +Three > Three +Four > Four +------------------------- +One > One +One,Two > One, Two +Three > Three +Four > Four +---------------------------------------------------------------------------------------------------- +XmlLib > is working properly. +---------------------------------------------------------------------------------------------------- +DeflateCompression(FileStream)-1 > is working properly. +DeflateCompression(FileStream)-2 > is working properly. +-------------------------------------------------- +DeflateCompression(MemoryStream) > is working properly. +---------------------------------------------------------------------------------------------------- +SQLUtility.GetUpdateSQLParts +[単一主キー] +- SQLServer +UPDATE Orders SET [Qty] = 100, [Note] = Convert(nvarchar(1), 'a') WHERE [OrderID] = 1 +UPDATE Orders SET [Qty] = 200, [Note] = Convert(nvarchar(1), 'b') WHERE [OrderID] = 2 +- Oracle +UPDATE Orders SET "Qty" = 100, "Note" = CAST('a' AS varchar2(1)) WHERE "OrderID" = 1 +UPDATE Orders SET "Qty" = 200, "Note" = CAST('b' AS varchar2(1)) WHERE "OrderID" = 2 +- PstGrS +UPDATE Orders SET "Qty" = CASE + WHEN "OrderID" = 1 THEN 100 + WHEN "OrderID" = 2 THEN 200 + ELSE "Qty" + END, + "Note" = CASE + WHEN "OrderID" = 1 THEN Cast('a' as text) + WHEN "OrderID" = 2 THEN Cast('b' as text) + ELSE "Note" + END +WHERE ("OrderID" = 1) + OR ("OrderID" = 2) +- MySQL +UPDATE Orders SET `Qty` = CASE + WHEN `OrderID` = 1 THEN 100 + WHEN `OrderID` = 2 THEN 200 + ELSE `Qty` + END, + `Note` = CASE + WHEN `OrderID` = 1 THEN Cast('a' as char(1)) + WHEN `OrderID` = 2 THEN Cast('b' as char(1)) + ELSE `Note` + END +WHERE (`OrderID` = 1) + OR (`OrderID` = 2) +[複合主キー] +- SQLServer +UPDATE Orders SET [Qty] = 100, [Note] = Convert(nvarchar(1), 'a') WHERE [OrderID] = 1 AND [ProductID] = 10 +UPDATE Orders SET [Qty] = 200, [Note] = Convert(nvarchar(1), 'b') WHERE [OrderID] = 2 AND [ProductID] = 20 +- Oracle +UPDATE Orders SET "Qty" = 100, "Note" = CAST('a' AS varchar2(1)) WHERE "OrderID" = 1 AND "ProductID" = 10 +UPDATE Orders SET "Qty" = 200, "Note" = CAST('b' AS varchar2(1)) WHERE "OrderID" = 2 AND "ProductID" = 20 +- PstGrS +UPDATE Orders SET "Qty" = CASE + WHEN "OrderID" = 1 AND "ProductID" = 10 THEN 100 + WHEN "OrderID" = 2 AND "ProductID" = 20 THEN 200 + ELSE "Qty" + END, + "Note" = CASE + WHEN "OrderID" = 1 AND "ProductID" = 10 THEN Cast('a' as text) + WHEN "OrderID" = 2 AND "ProductID" = 20 THEN Cast('b' as text) + ELSE "Note" + END +WHERE ("OrderID" = 1 AND "ProductID" = 10) + OR ("OrderID" = 2 AND "ProductID" = 20) +- MySQL +UPDATE Orders SET `Qty` = CASE + WHEN `OrderID` = 1 AND `ProductID` = 10 THEN 100 + WHEN `OrderID` = 2 AND `ProductID` = 20 THEN 200 + ELSE `Qty` + END, + `Note` = CASE + WHEN `OrderID` = 1 AND `ProductID` = 10 THEN Cast('a' as char(1)) + WHEN `OrderID` = 2 AND `ProductID` = 20 THEN Cast('b' as char(1)) + ELSE `Note` + END +WHERE (`OrderID` = 1 AND `ProductID` = 10) + OR (`OrderID` = 2 AND `ProductID` = 20) +[更新対象列なし] +- SQLServer +(生成なし) +- Oracle +(生成なし) +- PstGrS +(生成なし) +- MySQL +(生成なし) +[主キーなし] +- SQLServer +(生成なし) +- Oracle +(生成なし) +- PstGrS +(生成なし) +- MySQL +(生成なし) +---------------------------------------------------------------------------------------------------- +SQLUtility.GetInsertSQLParts +- SQLServer +([OrderID], [ProductID], [Qty], [Note]) +(1, 10, 100, Convert(nvarchar(1), 'a')) +(2, 20, 200, Convert(nvarchar(1), 'b')) +- Oracle +("OrderID", "ProductID", "Qty", "Note") +(1, 10, 100, CAST('a' AS varchar2(1))) +(2, 20, 200, CAST('b' AS varchar2(1))) +- PstGrS +("OrderID", "ProductID", "Qty", "Note") +(1, 10, 100, Cast('a' as text)) +(2, 20, 200, Cast('b' as text)) +- MySQL +(`OrderID`, `ProductID`, `Qty`, `Note`) +(1, 10, 100, Cast('a' as char(1))) +(2, 20, 200, Cast('b' as char(1))) +---------------------------------------------------------------------------------------------------- +log4net: Shutdown called on Hierarchy [log4net-default-repository] diff --git a/root/programs/CS/Frameworks/Tests/TestCode/TestSQLUtility.cs b/root/programs/CS/Frameworks/Tests/TestCode/TestSQLUtility.cs new file mode 100644 index 000000000..c73d7e653 --- /dev/null +++ b/root/programs/CS/Frameworks/Tests/TestCode/TestSQLUtility.cs @@ -0,0 +1,171 @@ +using System; +using System.Data; + +using Touryo.Infrastructure.Public.Db; +using Touryo.Infrastructure.Public.Diagnostics; + +namespace TestCode +{ + /// <summary>SQLUtilityのテスト</summary> + /// <remarks> + /// 生成されるSQLは、目視しないと誤りに気付けない。 + /// 特にPostgreSQL・MySQL向けの一括UPDATE(CASE ... WHEN ... THEN)は、 + /// 複合主キーで誤った行に誤った値を書き込む不具合があった(#515)。 + /// このため、生成結果を結果ファイルに残して比較できるようにする。 + /// </remarks> + public class TestSQLUtility + { + #region public + + /// <summary>Root</summary> + public static void Root() + { + TestSQLUtility.TestGetUpdateSQLParts(); + + MyDebug.OutputDebugAndConsole("----------------------------------------------------------------------------------------------------"); + + TestSQLUtility.TestGetInsertSQLParts(); + } + + #endregion + + #region private + + /// <summary>Update系SQLのパーツ生成のテスト</summary> + private static void TestGetUpdateSQLParts() + { + MyDebug.OutputDebugAndConsole("SQLUtility.GetUpdateSQLParts"); + + // 単一主キー + // ・PostgreSQL・MySQLは1文にまとめ、それ以外は1行1文になる。 + DataTable dtSingle = TestSQLUtility.CreateOrderTable(false); + TestSQLUtility.OutputUpdateSQLParts("単一主キー", dtSingle, new string[] { "OrderID" }); + + // 複合主キー + // ・WHENとWHEREが主キーの「組み合わせ」になっていること。 + // ・列ごとに独立していると、WHEREが直積になって対象外の行に一致し、 + // CASEも先に一致した枝が勝つため、誤った行に誤った値が入る(#515)。 + DataTable dtComposite = TestSQLUtility.CreateOrderTable(true); + TestSQLUtility.OutputUpdateSQLParts("複合主キー", dtComposite, new string[] { "OrderID", "ProductID" }); + + // 更新対象列が無い場合(全列が主キー) + // ・SET句が空のSQLは構文エラーになるため、生成しないこと。 + DataTable dtAllPk = new DataTable(); + dtAllPk.Columns.Add("OrderID", typeof(object)); + DataRow drAllPk = dtAllPk.NewRow(); + drAllPk["OrderID"] = 1; + dtAllPk.Rows.Add(drAllPk); + TestSQLUtility.OutputUpdateSQLParts("更新対象列なし", dtAllPk, new string[] { "OrderID" }); + + // 主キーが無い場合 + // ・WHERE句が無いと全行更新になるため、生成しないこと。 + TestSQLUtility.OutputUpdateSQLParts("主キーなし", dtSingle, new string[] { }); + } + + /// <summary>Insert系SQLのパーツ生成のテスト</summary> + private static void TestGetInsertSQLParts() + { + MyDebug.OutputDebugAndConsole("SQLUtility.GetInsertSQLParts"); + + DataTable dt = TestSQLUtility.CreateOrderTable(true); + + foreach (DbEnum.DBMSType dbms in TestSQLUtility.GetTargetDbms()) + { + MyDebug.OutputDebugAndConsole("- " + dbms.ToString()); + + string[] parts = (new SQLUtility(dbms)).GetInsertSQLParts(dt); + foreach (string part in parts) + { + MyDebug.OutputDebugAndConsole(part); + } + } + } + + /// <summary>Update系SQLのパーツを生成して出力する</summary> + /// <param name="caseName">ケース名</param> + /// <param name="dt">入力DataTable</param> + /// <param name="primaryKeys">主キー情報</param> + private static void OutputUpdateSQLParts(string caseName, DataTable dt, string[] primaryKeys) + { + MyDebug.OutputDebugAndConsole("[" + caseName + "]"); + + foreach (DbEnum.DBMSType dbms in TestSQLUtility.GetTargetDbms()) + { + MyDebug.OutputDebugAndConsole("- " + dbms.ToString()); + + string[] parts = (new SQLUtility(dbms)).GetUpdateSQLParts(dt, primaryKeys); + + if (parts.Length == 0) + { + // 生成しないケース(更新対象列なし・主キーなし) + MyDebug.OutputDebugAndConsole("(生成なし)"); + } + else + { + foreach (string part in parts) + { + // 呼び出し側が "UPDATE <テーブル名>" を前置して1文にする。 + MyDebug.OutputDebugAndConsole("UPDATE Orders " + part); + } + } + } + } + + /// <summary>テスト対象のDBMS</summary> + /// <returns>DBMSの種類の配列</returns> + /// <remarks> + /// HiRDBは囲い文字などの実装が他と同じため、代表としてSQLServerを見る。 + /// PostgreSQL・MySQLはCASE式を使う別実装のため、両方を対象にする。 + /// </remarks> + private static DbEnum.DBMSType[] GetTargetDbms() + { + return new DbEnum.DBMSType[] + { + DbEnum.DBMSType.SQLServer, + DbEnum.DBMSType.Oracle, + DbEnum.DBMSType.PstGrS, + DbEnum.DBMSType.MySQL + }; + } + + /// <summary>テスト用のDataTableを生成する</summary> + /// <param name="isComposite">主キーを複合にするか</param> + /// <returns>DataTable</returns> + private static DataTable CreateOrderTable(bool isComposite) + { + DataTable dt = new DataTable(); + + dt.Columns.Add("OrderID", typeof(object)); + if (isComposite) + { + dt.Columns.Add("ProductID", typeof(object)); + } + dt.Columns.Add("Qty", typeof(object)); + dt.Columns.Add("Note", typeof(object)); + + DataRow dr1 = dt.NewRow(); + dr1["OrderID"] = 1; + if (isComposite) + { + dr1["ProductID"] = 10; + } + dr1["Qty"] = 100; + dr1["Note"] = "a"; + dt.Rows.Add(dr1); + + DataRow dr2 = dt.NewRow(); + dr2["OrderID"] = 2; + if (isComposite) + { + dr2["ProductID"] = 20; + } + dr2["Qty"] = 200; + dr2["Note"] = "b"; + dt.Rows.Add(dr2); + + return dt; + } + + #endregion + } +} diff --git a/root/programs/CS/Frameworks/Tests/TestCode/core100/TestCodeCore.csproj b/root/programs/CS/Frameworks/Tests/TestCode/core100/TestCodeCore.csproj index 4aae226a3..68e97760c 100644 --- a/root/programs/CS/Frameworks/Tests/TestCode/core100/TestCodeCore.csproj +++ b/root/programs/CS/Frameworks/Tests/TestCode/core100/TestCodeCore.csproj @@ -21,6 +21,7 @@ <Compile Include="..\TestJISCode.cs" Link="TestJISCode.cs" /> <Compile Include="..\TestOutputLog.cs" Link="TestOutputLog.cs" /> <Compile Include="..\TestStringChecker.cs" Link="TestStringChecker.cs" /> + <Compile Include="..\TestSQLUtility.cs" Link="TestSQLUtility.cs" /> <Compile Include="..\TestStringConverter.cs" Link="TestStringConverter.cs" /> <Compile Include="..\TestXmlLib.cs" Link="TestXmlLib.cs" /> </ItemGroup> @@ -38,7 +39,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="log4net" Version="3.1.0" /> + <PackageReference Include="log4net" Version="3.3.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.6" /> diff --git a/root/programs/CS/Frameworks/Tests/TestCode/net48/TestCodeFx.csproj b/root/programs/CS/Frameworks/Tests/TestCode/net48/TestCodeFx.csproj index 2f17a61cd..358a40197 100644 --- a/root/programs/CS/Frameworks/Tests/TestCode/net48/TestCodeFx.csproj +++ b/root/programs/CS/Frameworks/Tests/TestCode/net48/TestCodeFx.csproj @@ -89,6 +89,9 @@ <Compile Include="..\TestStringChecker.cs"> <Link>TestStringChecker.cs</Link> </Compile> + <Compile Include="..\TestSQLUtility.cs"> + <Link>TestSQLUtility.cs</Link> + </Compile> <Compile Include="..\TestStringConverter.cs"> <Link>TestStringConverter.cs</Link> </Compile> diff --git a/root/programs/CS/Frameworks/Tests/TestLog/TestLog1.csproj b/root/programs/CS/Frameworks/Tests/TestLog/TestLog1.csproj index a72b73be8..a7722aebc 100644 --- a/root/programs/CS/Frameworks/Tests/TestLog/TestLog1.csproj +++ b/root/programs/CS/Frameworks/Tests/TestLog/TestLog1.csproj @@ -91,7 +91,7 @@ </ItemGroup> <ItemGroup> <PackageReference Include="log4net"> - <Version>3.1.0</Version> + <Version>3.3.0</Version> </PackageReference> <PackageReference Include="NLog"> <Version>5.5.0</Version> diff --git a/root/programs/CS/Frameworks/Tests/TestLog/TestLog2.csproj b/root/programs/CS/Frameworks/Tests/TestLog/TestLog2.csproj index b7b903009..3f4ae430a 100644 --- a/root/programs/CS/Frameworks/Tests/TestLog/TestLog2.csproj +++ b/root/programs/CS/Frameworks/Tests/TestLog/TestLog2.csproj @@ -91,7 +91,7 @@ </ItemGroup> <ItemGroup> <PackageReference Include="log4net"> - <Version>3.1.0</Version> + <Version>3.3.0</Version> </PackageReference> </ItemGroup> <ItemGroup> diff --git a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore1.csproj b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore1.csproj index 093e0b6c8..a78b72703 100644 --- a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore1.csproj +++ b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore1.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>WinExe</OutputType> - <TargetFramework>net8.0-windows7.0</TargetFramework> + <TargetFramework>net10.0-windows7.0</TargetFramework> <UseWindowsForms>true</UseWindowsForms> <ApplicationIcon /> <StartupObject /> @@ -42,7 +42,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="log4net" Version="3.1.0" /> + <PackageReference Include="log4net" Version="3.3.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.6" /> @@ -61,7 +61,7 @@ <ItemGroup> <Reference Include="OpenTouryo.Public"> - <HintPath>..\..\Infrastructure\Build_netcore80\net8.0\OpenTouryo.Public.dll</HintPath> + <HintPath>..\..\Infrastructure\Build_netcore100\net10.0\OpenTouryo.Public.dll</HintPath> </Reference> </ItemGroup> diff --git a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore2.csproj b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore2.csproj index c74f69554..159cda630 100644 --- a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore2.csproj +++ b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore2.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>WinExe</OutputType> - <TargetFramework>net8.0-windows7.0</TargetFramework> + <TargetFramework>net10.0-windows7.0</TargetFramework> <UseWindowsForms>true</UseWindowsForms> <ApplicationIcon /> <StartupObject /> @@ -42,7 +42,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="log4net" Version="3.1.0" /> + <PackageReference Include="log4net" Version="3.3.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.6" /> @@ -57,7 +57,7 @@ <ItemGroup> <Reference Include="OpenTouryo.Public"> - <HintPath>..\..\Infrastructure\Build_netcore80\net8.0\OpenTouryo.Public.dll</HintPath> + <HintPath>..\..\Infrastructure\Build_netcore100\net10.0\OpenTouryo.Public.dll</HintPath> </Reference> </ItemGroup> diff --git a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore3.csproj b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore3.csproj index c9c8b43ec..d787cab12 100644 --- a/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore3.csproj +++ b/root/programs/CS/Frameworks/Tests/TestLog/TestLogCore3.csproj @@ -2,7 +2,7 @@ <PropertyGroup> <OutputType>WinExe</OutputType> - <TargetFramework>net8.0-windows7.0</TargetFramework> + <TargetFramework>net10.0-windows7.0</TargetFramework> <UseWindowsForms>true</UseWindowsForms> <ApplicationIcon /> <StartupObject /> @@ -57,7 +57,7 @@ <ItemGroup> <Reference Include="OpenTouryo.Public"> - <HintPath>..\..\Infrastructure\Build_netcore80\net8.0\OpenTouryo.Public.dll</HintPath> + <HintPath>..\..\Infrastructure\Build_netcore100\net10.0\OpenTouryo.Public.dll</HintPath> </Reference> </ItemGroup> diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoDefinitionOptions.cs b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoDefinitionOptions.cs new file mode 100644 index 000000000..55f30c422 --- /dev/null +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoDefinitionOptions.cs @@ -0,0 +1,85 @@ +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :DaoDefinitionOptions +//* クラス日本語名 :D層定義情報ファイル生成処理のオプション +//* +//* 作成者 :玄人 幸道 +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2026/07/31 玄人 幸道 新規作成(GUIのCUI化) +//********************************************************************************** + +namespace DaoGen_Tool +{ + /// <summary> + /// D層定義情報ファイル生成処理のオプション + /// </summary> + /// <remarks> + /// 生成処理(Form1.DaoDefinitionGen)を GUI からも CUI からも呼び出せるようにするための引数。 + /// UI コントロールへの参照を持たず、フィールドは全て組み込み型とする。 + /// ・GUI 起動時は Form1 のイベント ハンドラが UI コントロールから値を読んで処理を呼び出す。 + /// ・CUI 起動時は Program がコマンドライン引数から生成する。 + /// </remarks> + public class DaoDefinitionOptions + { + #region 接続情報 + + /// <summary>データ プロバイダ(SQL / OLE / ODB / ODP / DB2 / HIR / MCN / NPS)</summary> + public string Dap = "SQL"; + + /// <summary>接続文字列</summary> + public string ConnectionString = ""; + + #endregion + + #region 出力 + + /// <summary>出力先ファイル(*.csv)へのパス</summary> + /// <remarks> + /// 同じ場所に "*_DBTypeInfo.csv" "*_DotNetTypeInfo.csv" も出力される。 + /// </remarks> + public string OutputFilePath = ""; + + /// <summary>D層定義情報ファイルの出力エンコーディング(コード ページ)</summary> + public int CodePage = 65001; + + #endregion + + #region 生成対象 + + /// <summary>生成対象とするテーブル・ビュー名の配列</summary> + /// <remarks>要素が無い場合は、DBMS 上の全テーブル・ビューを対象とする。</remarks> + public string[] Tables = new string[0]; + + /// <summary>生成対象から除外するテーブル・ビュー名の配列</summary> + public string[] ExcludeTables = new string[0]; + + /// <summary>主キー情報(キー:テーブル名、値:主キー列名の配列)</summary> + /// <remarks> + /// GUI の「主キー情報の設定」ダイアログに相当する。 + /// 主キー情報を DBMS から取得できないデータ プロバイダ + /// (ODBC・OLEDB・MySQL・PostgreSQL)で使用する。 + /// </remarks> + public System.Collections.Generic.Dictionary<string, string[]> PrimaryKeys + = new System.Collections.Generic.Dictionary<string, string[]>(); + + #endregion + } +} diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGenOptions.cs b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGenOptions.cs new file mode 100644 index 000000000..18e4f71ee --- /dev/null +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGenOptions.cs @@ -0,0 +1,134 @@ +#region Apache License +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#endregion + +//********************************************************************************** +//* クラス名 :DaoGenOptions +//* クラス日本語名 :Dao・DTO・SQL 生成処理のオプション +//* +//* 作成者 :玄人 幸道 +//* 更新履歴 : +//* +//* 日時 更新者 内容 +//* ---------- ---------------- ------------------------------------------------- +//* 2026/07/31 玄人 幸道 新規作成(GUIのCUI化) +//********************************************************************************** + +namespace DaoGen_Tool +{ + /// <summary> + /// Dao・DTO・SQL 生成処理のオプション + /// </summary> + /// <remarks> + /// 生成処理(Form2.DaoAndSqlGen)を GUI からも CUI からも呼び出せるようにするための引数。 + /// UI コントロールへの参照を持たず、フィールドは全て組み込み型とする。 + /// ・GUI 起動時は Form2 のイベント ハンドラが UI コントロールから値を読んで生成する。 + /// ・CUI 起動時は Program がコマンドライン引数から生成する。 + /// </remarks> + public class DaoGenOptions + { + #region 入出力パス + + /// <summary>D層定義情報ファイル(*.csv)へのパス</summary> + /// <remarks> + /// 同じ場所の "*_DotNetTypeInfo.csv" "*_DBTypeInfo.csv" も必要に応じて読み込まれる。 + /// </remarks> + public string DaoDefinitionFilePath = ""; + + /// <summary>テンプレート ファイルのルート フォルダ</summary> + public string TemplateRootPath = ""; + + /// <summary>出力先フォルダ</summary> + public string OutputPath = ""; + + #endregion + + #region データ プロバイダ・言語 + + /// <summary>データ プロバイダ(SQL / OLE / ODB / ODP / DB2 / MCN / NPS)</summary> + public string Dap = "SQL"; + + /// <summary>true:Visual C# / false:Visual Basic</summary> + public bool IsCSharp = true; + + #endregion + + #region 生成対象 + + /// <summary>エンティティ(DTO)を生成する</summary> + public bool CreateEntity = false; + + /// <summary>型付きデータセットを生成する</summary> + public bool CreateTypedDataSet = false; + + /// <summary>テーブル メンテナンス画面を生成する</summary> + public bool CreateTableMaintenance = false; + + /// <summary>DTO のみ生成する(Dao を生成しない)</summary> + public bool OnlyDTO = false; + + /// <summary>テーブル メンテナンス画面のみ生成する(Dao を生成しない)</summary> + public bool OnlyTableMaintenance = false; + + #endregion + + #region 生成オプション + + /// <summary>D層定義情報ファイルの1行目をヘッダとして読み飛ばす</summary> + public bool DaoDefinitionHeader = true; + + /// <summary>エスケープ文字(ODP 使用時に1文字必須)</summary> + public string EscapeChar = ""; + + /// <summary>タイム スタンプ列名(空文字なら未使用)</summary> + public string TimeStampColName = ""; + + /// <summary>タイム スタンプの更新方法</summary> + public string TimeStampUpdMethod = ""; + + /// <summary>作成者(姓)</summary> + public string FamilyName = ""; + + /// <summary>作成者(名)</summary> + public string PersonalName = ""; + + #endregion + + #region エンコーディング + + /// <summary>SQL ファイル(XML)のエンコーディング名</summary> + public string XmlEncoding = "utf-8"; + + /// <summary>クラス ファイルのエンコーディング(コード ページ)</summary> + public int ClassFileCodePage = 65001; + + /// <summary>D層定義情報ファイルの読み込みエンコーディング(コード ページ)</summary> + public int DaoDefinitionCodePage = 65001; + + /// <summary>クラス ファイルの出力エンコーディング(コード ページ)</summary> + public int ClassFileOutputCodePage = 65001; + + /// <summary>SQL ファイルの出力エンコーディング(コード ページ)</summary> + public int SqlFileCodePage = 65001; + + /// <summary>SQL テンプレートの読み込みエンコーディング(コード ページ)</summary> + public int SqlTemplateCodePage = 65001; + + /// <summary>LIKE 文(Oracle 用の LIKE 句の記述)</summary> + public string LikeStatement = "LIKE"; + + #endregion + } +} diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGen_Tool.csproj b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGen_Tool.csproj index a113774f5..d0fbbf84f 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGen_Tool.csproj +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/DaoGen_Tool.csproj @@ -108,6 +108,8 @@ <Compile Include="Form2.Designer.cs"> <DependentUpon>Form2.cs</DependentUpon> </Compile> + <Compile Include="DaoDefinitionOptions.cs" /> + <Compile Include="DaoGenOptions.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <EmbeddedResource Include="Form1.ja-JP.resx"> diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form1.cs b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form1.cs index a52a8c48f..fbc7bdd30 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form1.cs +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form1.cs @@ -50,6 +50,12 @@ //* 2014/08/19 西野 大介 カラム取得時のスキーマ考慮が無かったため追加(奥井さんからの提供) //* 2017/09/06 西野 大介 Oracle.ManagedDataAccess.Clientで主キーが取れなくなった対応 //* 2018/10/29 西野 大介 NETCOREAPP対応で、サポートされないDBを「#if」した。 +//* 2026/07/31 玄人 幸道 GUIのCUI化(イベント ハンドラのロジックを関数化) +//* 2026/08/01 玄人 幸道 SQL Serverの主キー取得を、非公開のストアド プロシージャ +//* (sp_helpconstraint/sp_MShelpindex)からカタログ ビューに変更 +//* 2026/08/01 玄人 幸道 サポートされないデータ プロバイダの選択・指定を抑止 +//* 2026/08/01 玄人 幸道 PostgreSQLの.NET型情報を取得するように変更 +//* (NpgsqlがDataTypesをサポートするようになったため) //********************************************************************************** // -------------------- @@ -76,6 +82,7 @@ using System.Text; using System.Data; using System.Collections; +using System.Collections.Generic; using System.Diagnostics; using System.Resources; using System.Drawing; @@ -128,6 +135,50 @@ public partial class Form1 : Form /// <summary>スキーマの情報(カスタム)</summary> private Hashtable HtSchemaCustom; + #region 取得したスキーマ情報(デバッグ表示用) + + // ↓↓↓【追加】↓↓↓ + // イベント ハンドラから外に出した関数の取得結果を、 + // イベント ハンドラ側でデバッグ表示するために保持する。 + + /// <summary>スキーマの情報(テーブル)</summary> + private DataTable DtSchmaTables; + + /// <summary>スキーマの情報(ビュー)</summary> + private DataTable DtSchmaViews; + + /// <summary>スキーマの情報(カラム)</summary> + private DataTable DtSchmaColumns; + + /// <summary>スキーマの情報(主キー)</summary> + private DataTable DtSchmaPrimaryKeys; + + /// <summary>スキーマの情報(インデックス カラム)</summary> + private DataTable DtSchmaIndexColumns; + + // ↑↑↑【追加】↑↑↑ + + #endregion + + #endregion + + #region CUI(ヘッドレス実行)用 + + // ↓↓↓【追加】↓↓↓ + + /// <summary>接続文字列</summary> + /// <remarks> + /// GUI 起動時はイベント ハンドラが txtConnString から、 + /// CUI 起動時は DaoDefinitionGen がコマンドライン引数から設定する。 + /// </remarks> + private string ConnString = ""; + + /// <summary>CUI(非対話)で起動しているか</summary> + /// <remarks>true の場合、MessageBox の代わりに標準出力へメッセージを出す。</remarks> + public bool IsCui = false; + + // ↑↑↑【追加】↑↑↑ + #endregion #region Help Information @@ -183,12 +234,21 @@ private void Form1_Load(object sender, EventArgs e) this.btnDaoDefinitionGen.Enabled = false; + // ↓↓↓【変更】↓↓↓ + // このビルドでサポートされないデータ プロバイダは、選択できないようにする。 + // ※ DB2・HiRDBは、両ビルドともコードがコメントアウトされているためサポートされない。 #if NETCOREAPP + // OLEDBは、NETCOREAPPではサポートされない。 this.rbnOLE.Enabled = false; this.rbnDB2.Enabled = false; this.rbnHiRDB.Enabled = false; #else + // PostgreSQLは、NETCOREAPPでのみサポートされる。 + this.rbnPstgrs.Enabled = false; + this.rbnDB2.Enabled = false; + this.rbnHiRDB.Enabled = false; #endif + // ↑↑↑【変更】↑↑↑ } #endregion @@ -211,59 +271,106 @@ private void Close_ToolStripMenuItem_Click(object sender, EventArgs e) #region 共通関数 + #region メッセージ表示 + + // ↓↓↓【追加】↓↓↓ + + /// <summary>メッセージを表示する(GUI:MessageBox/CUI:標準出力)</summary> + /// <param name="message">メッセージ</param> + private void ShowMessage(string message) + { + if (this.IsCui) + { + Console.WriteLine(message); + } + else + { + MessageBox.Show(message); + } + } + + /// <summary>メッセージを表示する(GUI:MessageBox/CUI:標準出力)</summary> + /// <param name="message">メッセージ</param> + /// <param name="caption">キャプション</param> + private void ShowMessage(string message, string caption) + { + if (this.IsCui) + { + Console.WriteLine(caption + " " + message); + } + else + { + MessageBox.Show(message, caption); + } + } + + // ↑↑↑【追加】↑↑↑ + + #endregion + #region コネクション オープン クローズ /// <summary> /// コネクション オープン /// </summary> + /// <remarks> + /// CUI からも呼び出せるよう、UIコントロール(rbnXxx、txtConnString)ではなく、 + /// this.Dap、this.ConnString を参照する。 + /// </remarks> private void ConnectionOpen() { - if (this.rbnSQL.Checked) + if (this.Dap == "SQL") { - this.SqlCn = new SqlConnection(this.txtConnString.Text); + this.SqlCn = new SqlConnection(this.ConnString); this.SqlCn.Open(); } - else if (this.rbnODB.Checked) + else if (this.Dap == "ODB") { - this.OdbCn = new OdbcConnection(this.txtConnString.Text); + this.OdbCn = new OdbcConnection(this.ConnString); this.OdbCn.Open(); } - else if (this.rbnODP.Checked) + else if (this.Dap == "ODP") { - this.OdpCn = new OracleConnection(this.txtConnString.Text); + this.OdpCn = new OracleConnection(this.ConnString); this.OdpCn.Open(); } - else if (this.rbnMySQL.Checked) + else if (this.Dap == "MCN") { - this.MySqlCn = new MySqlConnection(this.txtConnString.Text); + this.MySqlCn = new MySqlConnection(this.ConnString); this.MySqlCn.Open(); } #if NETCOREAPP - else if (this.rbnPstgrs.Checked) + else if (this.Dap == "NPS") { - this.NpgsqlCn = new NpgsqlConnection(this.txtConnString.Text); + this.NpgsqlCn = new NpgsqlConnection(this.ConnString); this.NpgsqlCn.Open(); } #else - else if (this.rbnOLE.Checked) + else if (this.Dap == "OLE") { - this.OleCn = new OleDbConnection(this.txtConnString.Text); + this.OleCn = new OleDbConnection(this.ConnString); this.OleCn.Open(); } - /*else if (this.rbnDB2.Checked) + /*else if (this.Dap == "DB2") { - this.DB2Cn = new DB2Connection(this.txtConnString.Text); + this.DB2Cn = new DB2Connection(this.ConnString); this.DB2Cn.Open(); } - else if (this.rbnHiRDB.Checked) + else if (this.Dap == "HIR") { - this.HiRDBCn = new HiRDBConnection(this.txtConnString.Text); + this.HiRDBCn = new HiRDBConnection(this.ConnString); this.HiRDBCn.Open(); }*/ #endif else { - // データプロバイダ指定無し(ありえない) + // ↓↓↓【変更】↓↓↓ + // データプロバイダ指定無し、または、このビルドでサポートされないデータ プロバイダ。 + // 以前は何もしなかったため、コネクションがnullのまま後続処理へ進み、 + // NullReferenceExceptionになっていた。呼び出し元のcatchで処理できるよう、例外を送出する。 + throw new NotSupportedException(string.Format( + "データ プロバイダ[{0}]は、このビルドではサポートされていません。", this.Dap)); + // ↑↑↑【変更】↑↑↑ } } @@ -573,6 +680,9 @@ private void btnGetSchemaInfo_Click(object sender, EventArgs e) // カーソルを待機状態にする System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; + // UIコントロールから情報を取得する。 + this.ConnString = this.txtConnString.Text; + // コネクション オープン this.ConnectionOpen(); @@ -1024,15 +1134,74 @@ private void btnGetSchemaInfo_Click(object sender, EventArgs e) /// <summary>スキーマ情報を読み込み、テーブル・ビューをリストする。</summary> private void btnListTable_Click(object sender, EventArgs e) + { + // カーソルを待機状態にする + System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; + + try + { + // UIコントロールから情報を取得し、リスト処理を呼び出す。 + this.ConnString = this.txtConnString.Text; + + if (!this.ListTable()) + { + // 失敗した場合、UIコントロールへの反映は行わない。 + return; + } + + #region デバッグ + if (this.cbxDebug.Checked) + { + // テーブル情報 + if (this.DtSchmaTables != null) + { + //this.tabPage1.Text = "テーブル情報"; + this.tabPage1.Text = this.RM_GetString("TabPage1TableInfo"); + this.dataGridView1.DataSource = this.DtSchmaTables; + } + // ヴュー情報 + if (this.DtSchmaViews != null) + { + //this.tabPage2.Text = "ヴュー情報"; + this.tabPage2.Text = this.RM_GetString("TabPage2VieuxInfo"); + this.dataGridView2.DataSource = this.DtSchmaViews; + } + } + #endregion + + // リスト ボックスを更新する。 + this.LbxUpdateItems(); + + // ボタン状態の変更 + this.gbxDataProviders.Enabled = false; + this.rbnMySQL.Enabled = false; + this.txtConnString.Enabled = false; + + this.btnDelTable.Enabled = true; + this.btnLoadColumn.Enabled = true; + + this.btnSetPrimaryKey.Enabled = false; + + this.cmbEncoding.Enabled = false; + this.btnDaoDefinitionGen.Enabled = false; + } + finally + { + // カーソルを元に戻す + System.Windows.Forms.Cursor.Current = Cursors.Default; + } + } + + /// <summary>スキーマ情報を読み込み、テーブル・ビューをリストする(GUI/CUI 共通)。</summary> + /// <returns>成功した場合 true</returns> + /// <remarks>UIコントロールを参照しないため、フォームを表示せずに呼び出せる。</remarks> + private bool ListTable() { try { // コネクション オープン this.ConnectionOpen(); - // カーソルを待機状態にする - System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; - // スキーマの情報(テーブル) DataTable dtSchmaTables = null; // スキーマの情報(ビュー) @@ -1040,13 +1209,13 @@ private void btnListTable_Click(object sender, EventArgs e) #region スキーマ情報を読み込み // テーブル・ビューをリストする。 - if (this.rbnSQL.Checked) + if (this.Dap == "SQL") { #region SQL Server // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(SQL Server用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "SQL Server"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(SQL Server用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "SQL Server"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1080,13 +1249,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } - else if (this.rbnODB.Checked) + else if (this.Dap == "ODB") { #region ODBC // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(ODBC用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "ODBC"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(ODBC用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "ODBC"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1120,14 +1289,14 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } - else if (this.rbnODP.Checked) + else if (this.Dap == "ODP") { #region Oracle #region ユーザー名を取得する。 // Substringする。 - string temp = this.txtConnString.Text; + string temp = this.ConnString; int start = temp.IndexOf("User Id=") + "User Id=".Length; int end = temp.IndexOf(";", start); temp = temp.Substring(start, end - start); @@ -1138,8 +1307,8 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion // 注釈 - //MessageBox.Show("[" + userId + "]スキーマ(ユーザ)の所有するテーブルのみを対象とします(Oracle用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisiteOracle"), userId), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("[" + userId + "]スキーマ(ユーザ)の所有するテーブルのみを対象とします(Oracle用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisiteOracle"), userId), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1183,13 +1352,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } - else if (this.rbnMySQL.Checked) + else if (this.Dap == "MCN") { #region MySQL // 注釈 - // MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(MySQL用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "MySQL"), this.RM_GetString("CautionPrerequisiteCaption")); + // this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(MySQL用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "MySQL"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1218,13 +1387,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } #if NETCOREAPP - else if (this.rbnPstgrs.Checked) + else if (this.Dap == "NPS") { #region PostgreSQL // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(PostgreSQL用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "PostgreSQL"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(PostgreSQL用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "PostgreSQL"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1255,13 +1424,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } #else - else if (this.rbnOLE.Checked) + else if (this.Dap == "OLE") { #region OLEDB // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(OLEDB用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "OLEDB"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(OLEDB用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "OLEDB"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 @@ -1295,13 +1464,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } - else if (this.rbnDB2.Checked) + else if (this.Dap == "DB2") { #region DB2 // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(DB2用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "DB2"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(DB2用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "DB2"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 /* @@ -1352,13 +1521,13 @@ private void btnListTable_Click(object sender, EventArgs e) #endregion } - else if (this.rbnHiRDB.Checked) + else if (this.Dap == "HIR") { #region HiRDB // 注釈 - //MessageBox.Show("同一DB上で同一名の複数のテーブルを持たないこと(HiRDB用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); - MessageBox.Show(string.Format(this.RM_GetString("CautionPrerequisite"), "ODBC"), this.RM_GetString("CautionPrerequisiteCaption")); + //this.ShowMessage("同一DB上で同一名の複数のテーブルを持たないこと(HiRDB用のD層自動生成ツールの仕様です)", "-注意(前提条件)-"); + this.ShowMessage(string.Format(this.RM_GetString("CautionPrerequisite"), "ODBC"), this.RM_GetString("CautionPrerequisiteCaption")); #region テーブル・ビューの情報を取得 /* @@ -1416,53 +1585,21 @@ private void btnListTable_Click(object sender, EventArgs e) } #endregion - #region デバッグ - if (this.cbxDebug.Checked) - { - // テーブル情報 - if (dtSchmaTables != null) - { - //this.tabPage1.Text = "テーブル情報"; - this.tabPage1.Text = this.RM_GetString("TabPage1TableInfo"); - this.dataGridView1.DataSource = dtSchmaTables; - } - // ヴュー情報 - if (dtSchmaViews != null) - { - //this.tabPage2.Text = "ヴュー情報"; - this.tabPage2.Text = this.RM_GetString("TabPage2VieuxInfo"); - this.dataGridView2.DataSource = dtSchmaViews; - } - } - #endregion - - // リスト ボックスを更新する。 - this.LbxUpdateItems(); - - // ボタン状態の変更 - this.gbxDataProviders.Enabled = false; - this.rbnMySQL.Enabled = false; - this.txtConnString.Enabled = false; - - this.btnDelTable.Enabled = true; - this.btnLoadColumn.Enabled = true; + // 取得したスキーマ情報を保持する(デバッグ表示用)。 + this.DtSchmaTables = dtSchmaTables; + this.DtSchmaViews = dtSchmaViews; - this.btnSetPrimaryKey.Enabled = false; - - this.cmbEncoding.Enabled = false; - this.btnDaoDefinitionGen.Enabled = false; + return true; } catch (Exception ex) { - MessageBox.Show(this.RM_GetString("RuntimeError") + ex.Message); + this.ShowMessage(this.RM_GetString("RuntimeError") + ex.Message); + return false; } finally { // コネクション クローズ this.ConnectionClose(); - - // カーソルを元に戻す - System.Windows.Forms.Cursor.Current = Cursors.Default; } } @@ -1478,6 +1615,67 @@ private void btnDelTable_Click(object sender, EventArgs e) /// <summary>スキーマ情報を読み込み、列情報をロードする。</summary> private void btnLoadColumn_Click(object sender, EventArgs e) + { + // カーソルを待機状態にする + System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; + + try + { + // UIコントロールから情報を取得し、ロード処理を呼び出す。 + this.ConnString = this.txtConnString.Text; + + if (!this.LoadColumn()) + { + // 失敗した場合、UIコントロールへの反映は行わない。 + return; + } + + #region デバッグ + if (this.cbxDebug.Checked) + { + // カラム情報 + if (this.DtSchmaColumns != null) + { + // this.tabPage1.Text = "カラム情報"; + this.tabPage1.Text = this.RM_GetString("TabPage1ColumnInfo"); + this.dataGridView1.DataSource = this.DtSchmaColumns; + } + // 主キー情報 + if (this.DtSchmaPrimaryKeys != null) + { + //this.tabPage2.Text = "主キー情報"; + this.tabPage2.Text = this.RM_GetString("TabPage2PrimarykeyInfo"); + this.dataGridView2.DataSource = this.DtSchmaPrimaryKeys; + } + // インデックス カラム情報 + if (this.DtSchmaIndexColumns != null) + { + //this.tabPage3.Text = "インデックス カラム情報"; + this.tabPage3.Text = this.RM_GetString("TabPage3IndexColInfo"); + this.dataGridView3.DataSource = this.DtSchmaIndexColumns; + } + } + #endregion + + // ボタン状態の変更 + this.btnLoadColumn.Enabled = false; + + this.btnSetPrimaryKey.Enabled = true; + + this.cmbEncoding.Enabled = true; + this.btnDaoDefinitionGen.Enabled = true; + } + finally + { + // カーソルを元に戻す + System.Windows.Forms.Cursor.Current = Cursors.Default; + } + } + + /// <summary>スキーマ情報を読み込み、列情報をロードする(GUI/CUI 共通)。</summary> + /// <returns>成功した場合 true</returns> + /// <remarks>UIコントロールを参照しないため、フォームを表示せずに呼び出せる。</remarks> + private bool LoadColumn() { try { @@ -1492,49 +1690,50 @@ private void btnLoadColumn_Click(object sender, EventArgs e) // コネクション オープン this.ConnectionOpen(); - // カーソルを待機状態にする - System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; - #region 型情報を取得 - if (this.rbnSQL.Checked) + if (this.Dap == "SQL") { // DataTypes CmnMethods.DataTypes = this.SqlCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - else if (this.rbnODB.Checked) + else if (this.Dap == "ODB") { // DataTypes CmnMethods.DataTypes = this.OdbCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - else if (this.rbnODP.Checked) + else if (this.Dap == "ODP") { // DataTypes CmnMethods.DataTypes = this.OdpCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - else if (this.rbnMySQL.Checked) + else if (this.Dap == "MCN") { // DataTypes CmnMethods.DataTypes = this.MySqlCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - else if (this.rbnPstgrs.Checked) +#if NETCOREAPP + // ↓↓↓【変更】↓↓↓ + // 以前のNpgsqlはDataTypesをサポートしていなかったため、型情報を取得していなかったが、 + // 現在はサポートされているため、他のデータ プロバイダと同様に取得する。 + else if (this.Dap == "NPS") { - //// DataTypes(NpgsqlではDataTypesがサポートされていない) - //CmnMethods.DataTypes = this.NpgsqlCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); + // DataTypes + CmnMethods.DataTypes = this.NpgsqlCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } -#if NETCOREAPP + // ↑↑↑【変更】↑↑↑ #else - else if (this.rbnOLE.Checked) + else if (this.Dap == "OLE") { // DataTypes CmnMethods.DataTypes = this.OleCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - /*else if (this.rbnDB2.Checked) + /*else if (this.Dap == "DB2") { // DataTypes CmnMethods.DataTypes = this.DB2Cn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); } - else if (this.rbnHiRDB.Checked) + else if (this.Dap == "HIR") { // DataTypes CmnMethods.DataTypes = this.HiRDBCn.GetSchema(System.Data.Common.DbMetaDataCollectionNames.DataTypes); @@ -1555,7 +1754,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) DataTable dtSchmaIndexColumns = null; #region 列情報をロード - if (this.rbnSQL.Checked) + if (this.Dap == "SQL") { #region SQL Server @@ -1595,115 +1794,69 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #region 主キーの情報を取得 - // テーブルを取得 - foreach (CTable table in this.HtSchemaCustom.Values) + // ↓↓↓【変更】↓↓↓ + // 以前は、sp_helpconstraint で主キー インデックス名を取得し、 + // sp_MShelpindex で主キー列名(indCol1~indCol16)を取得していたが、下記の理由でカタログ ビューに変更した。 + // ・sp_MShelpindex は非公開のストアド プロシージャであり、内部で一時テーブル(tempdbの照合順序)と + // sysindexes.name(DBの照合順序)を文字列比較するため、両者が異なる環境では照合順序の競合で失敗する。 + // ・主キーが16列までという制限があった。 + // ・テーブルごとに2回、DBへ問い合わせていた。 + // カタログ ビューの結合キーは全てID(整数)であるため、照合順序の影響を受けない。 + + // 主キー情報を取得 + SqlCommand cmdPrimaryKeys = new SqlCommand( + "SELECT t.name AS TABLE_NAME, c.name AS COLUMN_NAME, ic.key_ordinal AS KEY_ORDINAL" + + " FROM sys.indexes AS i" + + " INNER JOIN sys.index_columns AS ic" + + " ON i.object_id = ic.object_id AND i.index_id = ic.index_id" + + " INNER JOIN sys.columns AS c" + + " ON ic.object_id = c.object_id AND ic.column_id = c.column_id" + + " INNER JOIN sys.tables AS t ON i.object_id = t.object_id" + + " WHERE i.is_primary_key = 1" + + " ORDER BY t.name, ic.key_ordinal", this.SqlCn); + + dtSchmaPrimaryKeys = new DataTable(); + + SqlDataReader drd = cmdPrimaryKeys.ExecuteReader(); + dtSchmaPrimaryKeys.Load(drd); + drd.Close(); + + // 主キーの設定 + foreach (System.Data.DataRow row in dtSchmaPrimaryKeys.Rows) { - // 存在チェック - if (!((CTable)this.HtSchemaCustom[table.Name]).Effective) - { - continue; // 存在しない場合スキップする処理を追加 - } + // テーブルを取得 + CTable table = (CTable)this.HtSchemaCustom[(string)row["TABLE_NAME"]]; - // ワーク - SqlDataReader drd = null; - DataTable dtSchmaConstraint = new DataTable(); - DataTable dtSchmaIndex = new DataTable(); - - // 主キー名 - string pkName = ""; - // 主キーレコード - System.Data.DataRow pkRow = null; - - // sp_helpconstraintストアドプロシージャで、主キー インデックス名を取得 - SqlCommand cmd_sp_help = new SqlCommand("sp_helpconstraint", this.SqlCn); - cmd_sp_help.CommandType = CommandType.StoredProcedure; - cmd_sp_help.Parameters.Add(new SqlParameter("@objname", table.Name)); - - // sp_helpconstraintストアドプロシージャの結果セット(制約に関する結果セット) - drd = cmd_sp_help.ExecuteReader(); - drd.NextResult(); // 1つスキップする。 - dtSchmaConstraint.Load(drd); - drd.Close(); - - // 制約レコードを取得する。 - foreach (System.Data.DataRow row in dtSchmaConstraint.Rows) + // 有効なテーブルにのみ設定する。 + if (table == null) { - // 制約レコードが主キーか? - if (row["constraint_type"].ToString().IndexOf( - "PRIMARY KEY", StringComparison.CurrentCultureIgnoreCase) == -1) - { - // 主キーでない。 - } - else - { - // 主キーである。 - pkName = row["constraint_name"].ToString(); - break; - } + // 不明なテーブル } - - // 主キー インデックス名なしの場合 - if (pkName == "") { } else { - - // sp_MShelpindexストアドプロシージャで、主キー列名を取得 - SqlCommand sp_MShelpindex = new SqlCommand("sp_MShelpindex", this.SqlCn); - sp_MShelpindex.CommandType = CommandType.StoredProcedure; - sp_MShelpindex.Parameters.Add(new SqlParameter("@tablename", table.Name)); - - // sp_helpconstraintストアドプロシージャの結果セット(制約に関する結果セット) - drd = sp_MShelpindex.ExecuteReader(); - dtSchmaIndex.Load(drd); - drd.Close(); - - // 主キー レコードを取得する。 - foreach (System.Data.DataRow row in dtSchmaIndex.Rows) + // 有効なテーブル + if (table.Effective) { - // 主キー インデックスか? - if (row["name"].ToString() == pkName) - { - // 主キー インデックスである。 - pkRow = row; - break; - } - else - { - // 主キー インデックスでない。 - - } - } + // 主キー列 + CColumn column = (CColumn)table.HtColumns_Name[(string)row["COLUMN_NAME"]]; - // 主キー レコードなしの場合 - if (pkRow == null) { } - else - { - // 列のIsKeyフラグを立てる。 - for (int i = 1; i <= 16; i++) + // nullの時があるようなので、この場合は処理しない。 + if (column == null) { } + else { - // 主キー列 - CColumn column = (CColumn)table.HtColumns_Name[pkRow["indCol" + i.ToString()].ToString()]; - - // nullの時があるようなので、この場合は処理しない。 - if (column == null) - { - // 無い場合は抜ける。 - break; - } - else - { - column.IsKey = true; - } + // 列のIsKeyフラグを立てる。 + column.IsKey = true; } } } } + // ↑↑↑【変更】↑↑↑ #endregion #endregion } - else if (this.rbnODB.Checked) + else if (this.Dap == "ODB") { #region ODBC.NET @@ -1741,14 +1894,14 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } - else if (this.rbnODP.Checked) + else if (this.Dap == "ODP") { #region Oracle // 接続文字列から"User Id"値を取得。 - start = this.txtConnString.Text.IndexOf("User Id=") + "User Id=".Length; - end = this.txtConnString.Text.IndexOf(";", start); - userId = this.txtConnString.Text.Substring(start, end - start).Trim(); + start = this.ConnString.IndexOf("User Id=") + "User Id=".Length; + end = this.ConnString.IndexOf(";", start); + userId = this.ConnString.Substring(start, end - start).Trim(); #region カラムの情報を取得 @@ -1859,7 +2012,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } - else if (this.rbnMySQL.Checked) + else if (this.Dap == "MCN") { #region MySQL @@ -1899,7 +2052,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } #if NETCOREAPP - else if (this.rbnPstgrs.Checked) + else if (this.Dap == "NPS") { #region PostgreSQL @@ -1922,10 +2075,14 @@ private void btnLoadColumn_Click(object sender, EventArgs e) // 有効なテーブル if (table.Effective) { + // ↓↓↓【変更】↓↓↓ + // 以前はNpgsqlがDataTypesをサポートしていなかったため + // ".NET型情報"を"System.Object"固定にしていたが、 + // 現在はサポートされているため、他のデータ プロバイダと同様に変換する。 CColumn column = new CColumn( - (string)row["COLUMN_NAME"], (string)row["DATA_TYPE"], "System.Object"); - //CmnMethods.ConvertToDotNetTypeInfo((string)row["DATA_TYPE"])); - //(NpgsqlではDataTypesがサポートされていないため) + (string)row["COLUMN_NAME"], (string)row["DATA_TYPE"], + CmnMethods.ConvertToDotNetTypeInfo((string)row["DATA_TYPE"])); + // ↑↑↑【変更】↑↑↑ // ポジションをキーにしてカラムを追加 table.HtColumns_Position[row["ORDINAL_POSITION"].ToString()] = column; @@ -1940,7 +2097,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } #else - else if (this.rbnOLE.Checked) + else if (this.Dap == "OLE") { #region OLEDB.NET @@ -1979,7 +2136,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } - /*else if (this.rbnDB2.Checked) + /*else if (this.Dap == "DB2") { #region DB2 @@ -2018,7 +2175,7 @@ private void btnLoadColumn_Click(object sender, EventArgs e) #endregion } - else if (this.rbnHiRDB.Checked) + else if (this.Dap == "HIR") { #region HiRDB @@ -2064,52 +2221,22 @@ private void btnLoadColumn_Click(object sender, EventArgs e) } #endregion - #region デバッグ - if (this.cbxDebug.Checked) - { - // カラム情報 - if (dtSchmaColumns != null) - { - // this.tabPage1.Text = "カラム情報"; - this.tabPage1.Text = this.RM_GetString("TabPage1ColumnInfo"); - this.dataGridView1.DataSource = dtSchmaColumns; - } - // 主キー情報 - if (dtSchmaPrimaryKeys != null) - { - //this.tabPage2.Text = "主キー情報"; - this.tabPage2.Text = this.RM_GetString("TabPage2PrimarykeyInfo"); - this.dataGridView2.DataSource = dtSchmaPrimaryKeys; - } - // インデックス カラム情報 - if (dtSchmaIndexColumns != null) - { - //this.tabPage3.Text = "インデックス カラム情報"; - this.tabPage3.Text = this.RM_GetString("TabPage3IndexColInfo"); - this.dataGridView3.DataSource = dtSchmaIndexColumns; - } - } - #endregion - - // ボタン状態の変更 - this.btnLoadColumn.Enabled = false; - - this.btnSetPrimaryKey.Enabled = true; + // 取得したスキーマ情報を保持する(デバッグ表示用)。 + this.DtSchmaColumns = dtSchmaColumns; + this.DtSchmaPrimaryKeys = dtSchmaPrimaryKeys; + this.DtSchmaIndexColumns = dtSchmaIndexColumns; - this.cmbEncoding.Enabled = true; - this.btnDaoDefinitionGen.Enabled = true; + return true; } catch (Exception ex) { - MessageBox.Show(this.RM_GetString("RuntimeError") + ex.Message); + this.ShowMessage(this.RM_GetString("RuntimeError") + ex.Message); + return false; } finally { // コネクション クローズ this.ConnectionClose(); - - // カーソルを元に戻す - System.Windows.Forms.Cursor.Current = Cursors.Default; } } @@ -2169,111 +2296,135 @@ private void btnDaoDefinitionGen_Click(object sender, EventArgs e) sfd.Title = this.RM_GetString("SaveFileDialogTitle"); DialogResult dRet = sfd.ShowDialog(); - // ストリームライター - StreamWriter sw = null; - StreamWriter sw_DBTypeInfo = null; - StreamWriter sw_DotNetTypeInfo = null; + // カーソルを待機状態にする + System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; try { - // カーソルを待機状態にする - System.Windows.Forms.Cursor.Current = Cursors.WaitCursor; - if (dRet == DialogResult.OK) { // OKで - if (sfd.FileName == "") + // UIコントロールから情報を取得し、生成処理を呼び出す。 + if (this.WriteDaoDefinition(sfd.FileName, (int)this.cmbEncoding.SelectedValue)) { - // ファイルが指定されていない。 + // メッセージ + //MessageBox.Show("D層定義情報の生成完了!"); + MessageBox.Show(this.RM_GetString("DlayerGeneratedMessage")); } - else - { - // ファイルが指定されている。 + } + else + { + // メッセージ + //MessageBox.Show("操作はキャンセルされました。"); + MessageBox.Show(this.RM_GetString("DLayerCancelledmessage")); + } + } + finally + { + // カーソルを元に戻す + System.Windows.Forms.Cursor.Current = Cursors.Default; + } + } + + /// <summary>D層定義情報ファイルを出力する(GUI/CUI 共通)。</summary> + /// <param name="filePath">出力先ファイル パス(*.csv)</param> + /// <param name="codePage">出力エンコーディングのコード ページ</param> + /// <returns>成功した場合 true</returns> + /// <remarks>UIコントロールを参照しないため、フォームを表示せずに呼び出せる。</remarks> + private bool WriteDaoDefinition(string filePath, int codePage) + { + // ストリームライター + StreamWriter sw = null; + StreamWriter sw_DBTypeInfo = null; + StreamWriter sw_DotNetTypeInfo = null; + + try + { + if (filePath == "") + { + // ファイルが指定されていない。 + } + else + { + // ファイルが指定されている。 - // ファイル出力 + // ファイル出力 - // エンコーディングの指定 - Encoding enc = Encoding.GetEncoding((int)this.cmbEncoding.SelectedValue); + // エンコーディングの指定 + Encoding enc = Encoding.GetEncoding(codePage); - // ファイル ストリームを生成する。 - int temp = sfd.FileName.Length - 4; - sw = new StreamWriter(sfd.FileName, false, enc); - sw_DBTypeInfo = new StreamWriter(sfd.FileName.Substring(0, temp) + "_DBTypeInfo" + sfd.FileName.Substring(temp), false, enc); - sw_DotNetTypeInfo = new StreamWriter(sfd.FileName.Substring(0, temp) + "_DotNetTypeInfo" + sfd.FileName.Substring(temp), false, enc); + // ファイル ストリームを生成する。 + int temp = filePath.Length - 4; + sw = new StreamWriter(filePath, false, enc); + sw_DBTypeInfo = new StreamWriter(filePath.Substring(0, temp) + "_DBTypeInfo" + filePath.Substring(temp), false, enc); + sw_DotNetTypeInfo = new StreamWriter(filePath.Substring(0, temp) + "_DotNetTypeInfo" + filePath.Substring(temp), false, enc); - // ファイル ヘッダーを出力 - //sw.WriteLine("テーブル名,カラム情報~"); - sw.WriteLine(this.RM_GetString("TableNameColInfo")); - //sw_DBTypeInfo.WriteLine("テーブル名,カラムDB型情報~"); - sw_DBTypeInfo.WriteLine(this.RM_GetString("TableNameColDbTypeInfo")); - //sw_DotNetTypeInfo.WriteLine("テーブル名,カラム.NET型情報~"); - sw_DotNetTypeInfo.WriteLine(this.RM_GetString("TableNameColdotNetTypeInfo")); + // ファイル ヘッダーを出力 + //sw.WriteLine("テーブル名,カラム情報~"); + sw.WriteLine(this.RM_GetString("TableNameColInfo")); + //sw_DBTypeInfo.WriteLine("テーブル名,カラムDB型情報~"); + sw_DBTypeInfo.WriteLine(this.RM_GetString("TableNameColDbTypeInfo")); + //sw_DotNetTypeInfo.WriteLine("テーブル名,カラム.NET型情報~"); + sw_DotNetTypeInfo.WriteLine(this.RM_GetString("TableNameColdotNetTypeInfo")); - // テーブルを処理 - foreach (CTable table in this.HtSchemaCustom.Values) + // テーブルを処理 + foreach (CTable table in this.HtSchemaCustom.Values) + { + // 有効なテーブルだけ出力 + if (table.Effective) { - // 有効なテーブルだけ出力 - if (table.Effective) + // カラム ポジションを昇順にソートする + ArrayList sort = CmnMethods.sortColumn(table.HtColumns_Position); + + // 1行目 + string pk = ""; + string pk_DBTypeInfo = ""; + string pk_DotNetTypeInfo = ""; + // 2行目 + string _else = ""; + string _else_DBTypeInfo = ""; + string _else_DotNetTypeInfo = ""; + + // ソート後のカラム ポジション配列を廻す + foreach (Int32 position in sort) { - // カラム ポジションを昇順にソートする - ArrayList sort = CmnMethods.sortColumn(table.HtColumns_Position); - - // 1行目 - string pk = ""; - string pk_DBTypeInfo = ""; - string pk_DotNetTypeInfo = ""; - // 2行目 - string _else = ""; - string _else_DBTypeInfo = ""; - string _else_DotNetTypeInfo = ""; - - // ソート後のカラム ポジション配列を廻す - foreach (Int32 position in sort) - { - // カラムを取得 - CColumn column = (CColumn)table.HtColumns_Position[position.ToString()]; + // カラムを取得 + CColumn column = (CColumn)table.HtColumns_Position[position.ToString()]; - if (column.IsKey) - { - // 主キー列 // 1行目 - pk += column.Name + ","; - pk_DBTypeInfo += column.DBTypeInfo + ","; - pk_DotNetTypeInfo += column.DotNetTypeInfo + ","; - } - else - { - // その他の列 // 2行目 - _else += column.Name + ","; - _else_DBTypeInfo += column.DBTypeInfo + ","; - _else_DotNetTypeInfo += column.DotNetTypeInfo + ","; - } + if (column.IsKey) + { + // 主キー列 // 1行目 + pk += column.Name + ","; + pk_DBTypeInfo += column.DBTypeInfo + ","; + pk_DotNetTypeInfo += column.DotNetTypeInfo + ","; + } + else + { + // その他の列 // 2行目 + _else += column.Name + ","; + _else_DBTypeInfo += column.DBTypeInfo + ","; + _else_DotNetTypeInfo += column.DotNetTypeInfo + ","; } - - // 1行目 - sw.WriteLine(table.Name + "," + pk); - sw_DBTypeInfo.WriteLine(table.Name + "," + pk_DBTypeInfo); - sw_DotNetTypeInfo.WriteLine(table.Name + "," + pk_DotNetTypeInfo); - // 2行目 - sw.WriteLine("," + _else); - sw_DBTypeInfo.WriteLine("," + _else_DBTypeInfo); - sw_DotNetTypeInfo.WriteLine("," + _else_DotNetTypeInfo); } + + // 1行目 + sw.WriteLine(table.Name + "," + pk); + sw_DBTypeInfo.WriteLine(table.Name + "," + pk_DBTypeInfo); + sw_DotNetTypeInfo.WriteLine(table.Name + "," + pk_DotNetTypeInfo); + // 2行目 + sw.WriteLine("," + _else); + sw_DBTypeInfo.WriteLine("," + _else_DBTypeInfo); + sw_DotNetTypeInfo.WriteLine("," + _else_DotNetTypeInfo); } } - // メッセージ - //MessageBox.Show("D層定義情報の生成完了!"); - MessageBox.Show(this.RM_GetString("DlayerGeneratedMessage")); - } - else - { - // メッセージ - //MessageBox.Show("操作はキャンセルされました。"); - MessageBox.Show(this.RM_GetString("DLayerCancelledmessage")); } + + return true; } catch (Exception ex) { - MessageBox.Show(this.RM_GetString("RuntimeError") + ex.Message); + this.ShowMessage(this.RM_GetString("RuntimeError") + ex.Message); + return false; } finally { @@ -2307,12 +2458,209 @@ private void btnDaoDefinitionGen_Click(object sender, EventArgs e) // nullでない場合、閉じる。 sw_DotNetTypeInfo.Close(); } + } + } - // カーソルを元に戻す - System.Windows.Forms.Cursor.Current = Cursors.Default; + #endregion + + #region CUI(ヘッドレス実行) + + // ↓↓↓【追加】↓↓↓ + + /// <summary>D層定義情報ファイルを生成する(CUI)。</summary> + /// <param name="opt">生成オプション(UIコントロールに依存しない)</param> + /// <returns>成功した場合 true</returns> + /// <remarks> + /// GUI で「テーブルを一覧」→「列情報のロード」→「主キー情報の設定」 + /// →「D層定義情報の生成」と操作するのと同じ処理を、非対話で順に実行する。 + /// </remarks> + public bool DaoDefinitionGen(DaoDefinitionOptions opt) + { + // 接続情報の設定(GUIではラジオ ボタンとテキスト ボックスから設定される) + this.Dap = opt.Dap; + this.ConnString = opt.ConnectionString; + + // テーブル・ビューをリストする。 + if (!this.ListTable()) + { + return false; + } + + // 生成対象のテーブル・ビューを絞り込む。 + if (!this.SelectTables(opt.Tables, opt.ExcludeTables)) + { + return false; + } + + // 列情報をロードする。 + if (!this.LoadColumn()) + { + return false; + } + + // 主キー情報を設定する。 + if (!this.SetPrimaryKeys(opt.PrimaryKeys)) + { + return false; + } + + // 生成対象を表示する。 + foreach (CTable table in this.HtSchemaCustom.Values) + { + if (table.Effective) + { + this.ShowMessage("対象:" + table.Name); + } + } + + // D層定義情報ファイルを出力する。 + return this.WriteDaoDefinition(opt.OutputFilePath, opt.CodePage); + } + + /// <summary>生成対象のテーブル・ビューを絞り込む。</summary> + /// <param name="tables">生成対象とするテーブル・ビュー名の配列(空の場合は全て)</param> + /// <param name="excludeTables">生成対象から除外するテーブル・ビュー名の配列</param> + /// <returns>成功した場合 true</returns> + /// <remarks>GUI の「テーブルを削除(LbxDeleteItems)」に相当する。</remarks> + private bool SelectTables(string[] tables, string[] excludeTables) + { + // 生成対象の指定がある場合、指定されたテーブル・ビューのみを有効にする。 + if (tables != null && tables.Length != 0) + { + // 一旦、全て無効にする。 + foreach (CTable table in this.HtSchemaCustom.Values) + { + table.Effective = false; + } + + foreach (string tableName in tables) + { + CTable table = this.FindTable(tableName); + + if (table == null) + { + this.ShowMessage(string.Format( + "エラー:テーブル・ビュー[{0}]が見つかりません。", tableName)); + return false; + } + else + { + table.Effective = true; + } + } + } + + // 除外の指定がある場合、指定されたテーブル・ビューを無効にする。 + if (excludeTables != null) + { + foreach (string tableName in excludeTables) + { + CTable table = this.FindTable(tableName); + + if (table == null) + { + this.ShowMessage(string.Format( + "エラー:テーブル・ビュー[{0}]が見つかりません。", tableName)); + return false; + } + else + { + table.Effective = false; + } + } + } + + return true; + } + + /// <summary>主キー情報を設定する。</summary> + /// <param name="primaryKeys">主キー情報(キー:テーブル名、値:主キー列名の配列)</param> + /// <returns>成功した場合 true</returns> + /// <remarks> + /// GUI の「主キー情報の設定(SetPrimaryKeyWindow)」に相当する。 + /// 指定されたテーブルの主キーは、DBMS から取得した情報ではなく、この指定で置き換える。 + /// </remarks> + private bool SetPrimaryKeys(Dictionary<string, string[]> primaryKeys) + { + if (primaryKeys == null) + { + return true; + } + + foreach (KeyValuePair<string, string[]> kvp in primaryKeys) + { + CTable table = this.FindTable(kvp.Key); + + if (table == null) + { + this.ShowMessage(string.Format( + "エラー:テーブル・ビュー[{0}]が見つかりません。", kvp.Key)); + return false; + } + + // 指定されたテーブルの主キーを一旦クリアする。 + foreach (CColumn column in table.HtColumns_Name.Values) + { + column.IsKey = false; + } + + // 主キー列のIsKeyフラグを立てる。 + foreach (string columnName in kvp.Value) + { + CColumn column = this.FindColumn(table, columnName); + + if (column == null) + { + this.ShowMessage(string.Format( + "エラー:テーブル・ビュー[{0}]にカラム[{1}]が見つかりません。", + table.Name, columnName)); + return false; + } + else + { + column.IsKey = true; + } + } } + + return true; } + /// <summary>テーブル・ビューを検索する(大文字・小文字を区別しない)。</summary> + /// <param name="tableName">テーブル・ビュー名</param> + /// <returns>テーブル・ビュー(見つからない場合はnull)</returns> + private CTable FindTable(string tableName) + { + foreach (CTable table in this.HtSchemaCustom.Values) + { + if (string.Compare(table.Name, tableName, true) == 0) + { + return table; + } + } + + return null; + } + + /// <summary>カラムを検索する(大文字・小文字を区別しない)。</summary> + /// <param name="table">テーブル・ビュー</param> + /// <param name="columnName">カラム名</param> + /// <returns>カラム(見つからない場合はnull)</returns> + private CColumn FindColumn(CTable table, string columnName) + { + foreach (CColumn column in table.HtColumns_Name.Values) + { + if (string.Compare(column.Name, columnName, true) == 0) + { + return column; + } + } + + return null; + } + + // ↑↑↑【追加】↑↑↑ + #endregion /// <summary>D層、Daoクラスファイル、SQLファイルを生成する。</summary> diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form2.cs b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form2.cs index 401d95daf..4be2cbaef 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form2.cs +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Form2.cs @@ -52,6 +52,7 @@ //* added constant to get the TimeStamp placeholder from the app.config file and //* did code modification to replace the required TimeStamp code in the template, if TimeStamp selected in the tool. //* 2015/06/18 Sai-san Added <Else></Else> tag in create string method and ReplaceSQL method to fix the bug 'DynInsParameter of dynamic insert'. +//* 2026/07/31 玄人 幸道 GUIのCUI化(イベント ハンドラのロジックを関数化) //********************************************************************************** using System; @@ -822,10 +823,10 @@ private void OpenSrDefInfo(out StreamReader ddi, out StreamReader dti, out Strea Encoding enc = null; // DDE:D層定義情報のEncoding - enc = Encoding.GetEncoding((int)this.cmbDDEncoding.SelectedValue); + enc = Encoding.GetEncoding(this.genDaoDefCodePage); // 読込ファイル ストリームを生成する。 - ddi = new StreamReader(this.txtSetDaoDefinition.Text, enc); + ddi = new StreamReader(this.genDaoDefinitionFilePath, enc); // ↓↓↓【追加】↓↓↓ // +エンティテイ生成+型付きデータセット生成 @@ -866,12 +867,12 @@ private StreamReader OpenSrTemplate(string templateFilePath, int encoding) private StreamWriter OpenSwClassFile(string fileName, string extension) { // ファイルパス情報の作成 - string tempPath = this.CreateFilePath(this.txtSetOutput.Text, fileName, extension); + string tempPath = this.CreateFilePath(this.genOutputPath, fileName, extension); // 書込ファイル ストリームを生成する。 // DFE:DaoClassファイルのEncoding - return new StreamWriter(tempPath, false, Encoding.GetEncoding((int)this.cmbDFEncoding.SelectedValue)); + return new StreamWriter(tempPath, false, Encoding.GetEncoding(this.genClassFileCodePage)); } /// <summary>SQLファイルを開く(書込)</summary> @@ -880,12 +881,12 @@ private StreamWriter OpenSwClassFile(string fileName, string extension) private StreamWriter OpenSwSQLFile(string fileName, string extension) { // ファイルパス情報の作成 - string tempPath = this.CreateFilePath(this.txtSetOutput.Text, fileName, extension); + string tempPath = this.CreateFilePath(this.genOutputPath, fileName, extension); // 書込ファイル ストリームを生成する。 // SFE:SQLファイルのEncoding - return new StreamWriter(tempPath, false, Encoding.GetEncoding((int)this.cmbSFEncoding.SelectedValue)); + return new StreamWriter(tempPath, false, Encoding.GetEncoding(this.genSqlFileCodePage)); } #endregion @@ -1032,6 +1033,17 @@ private void Form2_Load(object sender, EventArgs e) #endregion + // 設定ファイルからの読み込み + // (UIコントロールに依存しないため、CUIからも呼び出せるよう関数化している) + this.LoadSettingsFromConfig(); + } + + /// <summary> + /// 設定ファイルからテンプレート ファイル名・クラス名・メソッド名などを読み込む(GUI/CUI 共通)。 + /// </summary> + /// <remarks>UIコントロールを参照しないため、フォームを表示せずに呼び出せる。</remarks> + public void LoadSettingsFromConfig() + { #region ファイル名、クラス名、メソッド名(+空文字チェック) #region 読み @@ -1920,9 +1932,116 @@ private void btnSetOutput_Click(object sender, EventArgs e) // メイン ロジック #region 生成処理 + + /// <summary>生成処理が使用するD層定義情報ファイルのパス</summary> + /// <remarks>DaoAndSqlGen の冒頭で DaoGenOptions から設定する(ファイルI/Oヘルパーが参照)。</remarks> + private string genDaoDefinitionFilePath = ""; + + /// <summary>生成処理が使用する出力先フォルダ</summary> + private string genOutputPath = ""; + + /// <summary>D層定義情報ファイルの読み込みコード ページ</summary> + private int genDaoDefCodePage = 65001; + + /// <summary>クラス ファイルの出力コード ページ</summary> + private int genClassFileCodePage = 65001; + + /// <summary>SQL ファイルの出力コード ページ</summary> + private int genSqlFileCodePage = 65001; + + /// <summary>SQL テンプレートの読み込みコード ページ</summary> + private int genSqlTemplateCodePage = 65001; + + /// <summary>LIKE 文</summary> + private string genLikeStatement = "LIKE"; + + /// <summary>エスケープ文字</summary> + private string genEscapeChar = ""; + + /// <summary>CUI(非対話)で起動しているか</summary> + /// <remarks>true の場合、MessageBox の代わりに標準出力へメッセージを出す。</remarks> + public bool IsCui = false; + + /// <summary>メッセージを表示する(GUI:MessageBox/CUI:標準出力)</summary> + /// <param name="message">メッセージ</param> + private void ShowMessage(string message) + { + if (this.IsCui) + { + Console.WriteLine(message); + } + else + { + MessageBox.Show(message); + } + } + + /// <summary>UIコントロールから生成オプションを組み立てる</summary> + /// <returns>生成オプション</returns> + /// <remarks>UIコントロールへの参照は、このメソッドとイベント ハンドラにのみ置く。</remarks> + private DaoGenOptions CreateOptionsFromUI() + { + DaoGenOptions opt = new DaoGenOptions(); + + // 入出力パス + opt.DaoDefinitionFilePath = this.txtSetDaoDefinition.Text; + opt.TemplateRootPath = this.txtSetSourceTemplate.Text; + opt.OutputPath = this.txtSetOutput.Text; + + // データ プロバイダ・言語 + opt.Dap = this.strDAP; + opt.IsCSharp = this.rbnDTL_CS.Checked; + + // 生成対象 + opt.CreateEntity = this.cbxEntity.Checked; + opt.CreateTypedDataSet = this.cbxTypedDataSet.Checked; + opt.CreateTableMaintenance = this.cbxTableMaintenance.Checked; + opt.OnlyDTO = this.cbxOnlyDTO.Checked; + opt.OnlyTableMaintenance = this.cbxOnlyTableMaintenance.Checked; + + // 生成オプション + opt.DaoDefinitionHeader = this.cbxDaoDefinitionHeader.Checked; + opt.EscapeChar = this.txtEscapeChar.Text; + opt.TimeStampColName = this.txtTimeStampColName.Text; + opt.TimeStampUpdMethod = this.txtTimeStampUpdMethod.Text; + opt.FamilyName = this.txtFamilyName.Text; + opt.PersonalName = this.txtPersonalName.Text; + + // エンコーディング + opt.XmlEncoding = this.cmbSFEncoding.Text; + opt.ClassFileCodePage = (int)this.cmbDTEncoding.SelectedValue; + opt.DaoDefinitionCodePage = (int)this.cmbDDEncoding.SelectedValue; + opt.ClassFileOutputCodePage = (int)this.cmbDFEncoding.SelectedValue; + opt.SqlFileCodePage = (int)this.cmbSFEncoding.SelectedValue; + opt.SqlTemplateCodePage = (int)this.cmbSTEncoding.SelectedValue; + opt.LikeStatement = this.cmbLikeStatement.Text; + + return opt; + } + /// <summary>D層、Daoクラスファイル、SQLファイルを生成する。</summary> private void btnDaoAndSqlGen_Click(object sender, EventArgs e) { + // UIコントロールから情報を取得し、生成処理を呼び出す。 + this.DaoAndSqlGen(this.CreateOptionsFromUI()); + } + + /// <summary>D層、Daoクラスファイル、SQLファイルを生成する(GUI/CUI 共通)。</summary> + /// <param name="opt">生成オプション(UIコントロールに依存しない)</param> + /// <returns>成功した場合 true</returns> + public bool DaoAndSqlGen(DaoGenOptions opt) + { + // ファイルI/Oヘルパー(OpenSrDefInfo/OpenSwClassFile/OpenSwSQLFile)が + // 参照するフィールドを設定する。 + this.genDaoDefinitionFilePath = opt.DaoDefinitionFilePath; + this.genOutputPath = opt.OutputPath; + this.genDaoDefCodePage = opt.DaoDefinitionCodePage; + this.genClassFileCodePage = opt.ClassFileOutputCodePage; + this.genSqlFileCodePage = opt.SqlFileCodePage; + this.genSqlTemplateCodePage = opt.SqlTemplateCodePage; + this.genLikeStatement = opt.LikeStatement; + this.genEscapeChar = opt.EscapeChar; + // D層定義情報ファイル StreamReader srDaoDef = null; @@ -1931,10 +2050,10 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) StreamReader srTypeDef = null; // DTO生成フラグの初期化 - this.CreateDTO = (this.cbxEntity.Checked || this.cbxTypedDataSet.Checked); + this.CreateDTO = (opt.CreateEntity || opt.CreateTypedDataSet); // メンテナンス画面生成フラグの初期化 - this.CreateMaintenanceScreen = (this.cbxOnlyTableMaintenance.Checked || this.cbxTableMaintenance.Checked); + this.CreateMaintenanceScreen = (opt.OnlyTableMaintenance || opt.CreateTableMaintenance); // ↑↑↑【追加】↑↑↑ @@ -1943,7 +2062,7 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) StreamReader srDbTypeDef = null; // DB型定義情報ファイル読み込みフラグ設定 - this.ReadDbTypeInfo = (this.ReadDbTypeInfo || rbnODP.Checked); + this.ReadDbTypeInfo = (this.ReadDbTypeInfo || (opt.Dap == "ODP")); // ↑↑↑【追加】↑↑↑ try @@ -1953,7 +2072,7 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region 拡張子の設定 - if (this.rbnDTL_CS.Checked) + if (opt.IsCSharp) { // Visual C# this.ClassTemplateFileExtension = "cs"; @@ -1978,13 +2097,13 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region D層定義情報ファイル // 標準生成 - fileInfo = new FileInfo(this.txtSetDaoDefinition.Text); + fileInfo = new FileInfo(opt.DaoDefinitionFilePath); if (fileInfo.Exists) { } else { - //MessageBox.Show(string.Format("チェックエラーです:D層定義情報ファイル[{0}]が存在しません。", fileInfo.Name)); - MessageBox.Show(string.Format(this.RM_GetString("FilenotExistDlayerInfo"), fileInfo.Name)); - return; + //this.ShowMessage(string.Format("チェックエラーです:D層定義情報ファイル[{0}]が存在しません。", fileInfo.Name)); + this.ShowMessage(string.Format(this.RM_GetString("FilenotExistDlayerInfo"), fileInfo.Name)); + return false; } // ↓↓↓【追加】↓↓↓ @@ -1992,19 +2111,19 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) if (this.CreateDTO) { // *.CSVである前提の仕様だがOKか?(一応ファイル名を出力する) - int temp = this.txtSetDaoDefinition.Text.Length - 4; + int temp = opt.DaoDefinitionFilePath.Length - 4; this.DotNetTypeInfoFilePath = - this.txtSetDaoDefinition.Text.Substring(0, temp) - + "_DotNetTypeInfo" + this.txtSetDaoDefinition.Text.Substring(temp); + opt.DaoDefinitionFilePath.Substring(0, temp) + + "_DotNetTypeInfo" + opt.DaoDefinitionFilePath.Substring(temp); fileInfo = new FileInfo(this.DotNetTypeInfoFilePath); if (fileInfo.Exists) { } else { - //MessageBox.Show(string.Format("チェックエラーです:.NET型情報ファイル[{0}]が存在しません。", fileInfo.Name)); - MessageBox.Show(string.Format(this.RM_GetString("FilenotExistNETtypeInfo"), fileInfo.Name)); - return; + //this.ShowMessage(string.Format("チェックエラーです:.NET型情報ファイル[{0}]が存在しません。", fileInfo.Name)); + this.ShowMessage(string.Format(this.RM_GetString("FilenotExistNETtypeInfo"), fileInfo.Name)); + return false; } } // ↑↑↑【追加】↑↑↑ @@ -2014,18 +2133,18 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) if (this.ReadDbTypeInfo) { // *.CSVである前提の仕様だがOKか?(一応ファイル名を出力する) - int temp = this.txtSetDaoDefinition.Text.Length - 4; + int temp = opt.DaoDefinitionFilePath.Length - 4; - this.DbTypeInfoFilePath = this.txtSetDaoDefinition.Text.Substring(0, temp) - + "_DBTypeInfo" + this.txtSetDaoDefinition.Text.Substring(temp); + this.DbTypeInfoFilePath = opt.DaoDefinitionFilePath.Substring(0, temp) + + "_DBTypeInfo" + opt.DaoDefinitionFilePath.Substring(temp); fileInfo = new FileInfo(this.DbTypeInfoFilePath); if (fileInfo.Exists) { } else { - //MessageBox.Show(string.Format("チェックエラーです:DB型情報ファイル[{0}]が存在しません。", fileInfo.Name)); - MessageBox.Show(string.Format(this.RM_GetString("FilenotExistDBtypeInfo"), fileInfo.Name)); - return; + //this.ShowMessage(string.Format("チェックエラーです:DB型情報ファイル[{0}]が存在しません。", fileInfo.Name)); + this.ShowMessage(string.Format(this.RM_GetString("FilenotExistDBtypeInfo"), fileInfo.Name)); + return false; } } // ↑↑↑【追加】↑↑↑ @@ -2034,26 +2153,26 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region 入力ファイル - dirInfo = new DirectoryInfo(this.txtSetSourceTemplate.Text); + dirInfo = new DirectoryInfo(opt.TemplateRootPath); if (dirInfo.Exists) { } else { - //MessageBox.Show("入力ファイル(テンプレート ファイル)のルート フォルダが存在しません。"); - MessageBox.Show(this.RM_GetString("InputFileRootFolderNotExist")); - return; + //this.ShowMessage("入力ファイル(テンプレート ファイル)のルート フォルダが存在しません。"); + this.ShowMessage(this.RM_GetString("InputFileRootFolderNotExist")); + return false; } #region Dao、Entity、DataSetテンプレート ファイル // Daoテンプレート ファイル - if (!this.cbxOnlyDTO.Checked - && !this.cbxOnlyTableMaintenance.Checked) + if (!opt.OnlyDTO + && !opt.OnlyTableMaintenance) { this.DaoTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DaoTemplateFileName, this.ClassTemplateFileExtension); } @@ -2064,14 +2183,14 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // Entityテンプレート ファイル this.EntityTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.EntityTemplateFileName, this.ClassTemplateFileExtension); // DataSetテンプレート ファイル this.DataSetTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DataSetTemplateFileName, ""); } @@ -2080,55 +2199,55 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // TableAdapterテンプレート ファイル this.TableAdapterTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.TableAdapterTemplateFileName, this.ClassTemplateFileExtension); // ConditionalSearchテンプレート ファイル this.ConditionalSearchTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.ConditionalSearchTemplateFileName, ""); // SearchAndUpdateテンプレート ファイル this.SearchAndUpdateTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.SearchAndUpdateTemplateFileName, ""); // Detailテンプレート ファイル this.DetailTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DetailTemplateFileName, ""); } // ↑↑↑【追加】↑↑↑ #endregion - if (!this.cbxOnlyDTO.Checked - && !this.cbxOnlyTableMaintenance.Checked) + if (!opt.OnlyDTO + && !opt.OnlyTableMaintenance) { #region SQLテンプレート ファイル(静的) this.InsertTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.InsertTemplateFileName, ""); this.SelectTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.SelectTemplateFileName, ""); this.UpdateTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.UpdateTemplateFileName, ""); this.DeleteTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DeleteTemplateFileName, ""); #endregion @@ -2137,28 +2256,28 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) this.DynInsTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DynInsTemplateFileName, ""); this.DynSelTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DynSelTemplateFileName, ""); this.DynUpdTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DynUpdTemplateFileName, ""); this.DynDelTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DynDelTemplateFileName, ""); // ↓↓↓【追加】↓↓↓ this.DynSelCntTemplateFilePath = this.CheckTemplateFile( - this.txtSetSourceTemplate.Text, + opt.TemplateRootPath, this.DynSelCntTemplateFileName, ""); // ↑↑↑【追加】↑↑↑ @@ -2169,13 +2288,13 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region 出力ファイル - dirInfo = new DirectoryInfo(this.txtSetOutput.Text); + dirInfo = new DirectoryInfo(opt.OutputPath); if (dirInfo.Exists) { } else { - //MessageBox.Show("出力ファイル(Daoクラス ファイル、SQLファイル.etc)のルート フォルダが存在しません。"); - MessageBox.Show(this.RM_GetString("OutputFileRootFolderNotExist")); - return; + //this.ShowMessage("出力ファイル(Daoクラス ファイル、SQLファイル.etc)のルート フォルダが存在しません。"); + this.ShowMessage(this.RM_GetString("OutputFileRootFolderNotExist")); + return false; } #endregion @@ -2185,12 +2304,12 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // ↓↓↓【追加】↓↓↓ //エスケープ文字のチェック - if (rbnODP.Checked == true && txtEscapeChar.Text.Length != 1) + if ((opt.Dap == "ODP") == true && opt.EscapeChar.Length != 1) { //Oracle ODP.NET かつ エスケープ文字が入力されていない(1文字でない)場合 - //MessageBox.Show("エスケープ文字が設定されていません。"); - MessageBox.Show(this.RM_GetString("EscCharacterNotSet")); - return; + //this.ShowMessage("エスケープ文字が設定されていません。"); + this.ShowMessage(this.RM_GetString("EscCharacterNotSet")); + return false; } // ↑↑↑【追加】↑↑↑ @@ -2200,10 +2319,10 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region タイムスタンプ列 // タイムスタンプ列名を取得 - this.TimeStampColName = this.txtTimeStampColName.Text.Trim(); + this.TimeStampColName = opt.TimeStampColName.Trim(); // タイムスタンプ更新方法を取得 - this.TimeStampUpdMethod = this.txtTimeStampUpdMethod.Text.Trim(); + this.TimeStampUpdMethod = opt.TimeStampUpdMethod.Trim(); // タイムスタンプの設定ステータスのチェック&設定 if (this.TimeStampColName == "" & this.TimeStampUpdMethod == "") @@ -2224,10 +2343,10 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) else { // 更新方法だけある。 - //MessageBox.Show("タイムスタンプ列名がありません。"); - MessageBox.Show(this.RM_GetString("NoTimestampColName")); + //this.ShowMessage("タイムスタンプ列名がありません。"); + this.ShowMessage(this.RM_GetString("NoTimestampColName")); - return; + return false; } #endregion @@ -2242,41 +2361,41 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) this.TimeStamp = DateTime.Now.Year + "/" + DateTime.Now.Month + "/" + DateTime.Now.Day; // ユーザ名 - this.UserName = this.txtFamilyName.Text + " " + this.txtPersonalName.Text; + this.UserName = opt.FamilyName + " " + opt.PersonalName; //// エンコーディング(XML用) - this.XMLEncoding = this.cmbSFEncoding.Text; + this.XMLEncoding = opt.XmlEncoding; // SQLの制御文字 - if (rbnSQL.Checked || rbnOLE.Checked || rbnODB.Checked) + if ((opt.Dap == "SQL") || (opt.Dap == "OLE") || (opt.Dap == "ODB")) { this.ParamSign = '@'; this.EnclosureCharS = '['; this.EnclosureCharE = ']'; } - else if (rbnODP.Checked) + else if ((opt.Dap == "ODP")) { this.ParamSign = ':'; this.EnclosureCharS = '"'; this.EnclosureCharE = '"'; } - else if (rbnDB2.Checked) + else if ((opt.Dap == "DB2")) { this.ParamSign = '@'; this.EnclosureCharS = '"'; this.EnclosureCharE = '"'; } - else if (rbnMySQL.Checked) + else if ((opt.Dap == "MCN")) { this.ParamSign = '@'; this.EnclosureCharS = '`'; this.EnclosureCharE = '`'; } - else if (rbnPstgrs.Checked) + else if ((opt.Dap == "NPS")) { // Npgsqlでは、「@」・「:」の双方をサポートするが、 // 本Fxでは、「:」を選択(動作がOracleに近いため)。 @@ -2318,7 +2437,7 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) #region D層定義情報ファイル ヘッダー制御 - if (this.cbxDaoDefinitionHeader.Checked) + if (opt.DaoDefinitionHeader) { // ヘッダーは、無視 if (!srDaoDef.EndOfStream) @@ -2770,7 +2889,7 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) this.DaoClassName = this.DaoClassNameHeader + this.TableName.Replace(' ', '_') + this.DaoClassNameFooter; // DTO、メンテナンス画面のみの場合はDao、SQLは生成しない。 - if (!(this.cbxOnlyDTO.Checked || this.cbxOnlyTableMaintenance.Checked)) + if (!(opt.OnlyDTO || opt.OnlyTableMaintenance)) { #region SQLファイルを生成 @@ -2952,18 +3071,18 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // DTE:DaoClassテンプレートのEncoding this.GenerateClassFile( this.DaoTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); #endregion } // ↓↓↓【追加】↓↓↓ if (this.CreateDTO - && !this.cbxOnlyTableMaintenance.Checked) + && !opt.OnlyTableMaintenance) { #region Entityファイルを生成 - if (this.cbxEntity.Checked) + if (opt.CreateEntity) { // カレント・ファイル出力用とReplace用途 // Entityクラス名 @@ -2977,14 +3096,14 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // DTE:DaoClassテンプレートのEncoding this.GenerateClassFile( this.EntityTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); } #endregion #region DataSetファイルを生成 - if (this.cbxTypedDataSet.Checked) + if (opt.CreateTypedDataSet) { // カレント・ファイル出力用とReplace用途 // DataSetクラス名 @@ -3002,14 +3121,14 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // DTE:DaoClassテンプレートのEncoding this.GenerateClassFile( this.DataSetTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); } #endregion } if (this.CreateMaintenanceScreen - && !this.cbxOnlyDTO.Checked) + && !opt.OnlyDTO) { // カレント・ファイル出力用とReplace用途 @@ -3017,7 +3136,7 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) this.FileName = this.TableName.Replace(' ', '_') + this.TableAdapterTemplateFileName; this.GenerateClassFile( this.TableAdapterTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); #region ASPXファイル、Codebehindファイル @@ -3025,29 +3144,29 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) this.FileName = this.TableName + this.ConditionalSearchTemplateFileName; this.GenerateClassFile( this.ConditionalSearchTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); this.GenerateClassFile( this.ConditionalSearchTemplateFilePath + "." + this.ClassTemplateFileExtension, - (int)this.cmbDTEncoding.SelectedValue, this.FileName + "." + this.ClassTemplateFileExtension); + opt.ClassFileCodePage, this.FileName + "." + this.ClassTemplateFileExtension); // ASPXファイル、Codebehindファイル(SearchAndUpdate)を生成 this.FileName = this.TableName + this.SearchAndUpdateTemplateFileName; this.GenerateClassFile( this.SearchAndUpdateTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); this.GenerateClassFile( this.SearchAndUpdateTemplateFilePath + "." + this.ClassTemplateFileExtension, - (int)this.cmbDTEncoding.SelectedValue, this.FileName + "." + this.ClassTemplateFileExtension); + opt.ClassFileCodePage, this.FileName + "." + this.ClassTemplateFileExtension); // ASPXファイル、Codebehindファイル(Detail)を生成 this.FileName = this.TableName + this.DetailTemplateFileName; this.GenerateClassFile( this.DetailTemplateFilePath, - (int)this.cmbDTEncoding.SelectedValue, this.FileName); + opt.ClassFileCodePage, this.FileName); this.GenerateClassFile( this.DetailTemplateFilePath + "." + this.ClassTemplateFileExtension, - (int)this.cmbDTEncoding.SelectedValue, this.FileName + "." + this.ClassTemplateFileExtension); + opt.ClassFileCodePage, this.FileName + "." + this.ClassTemplateFileExtension); #endregion } @@ -3073,19 +3192,22 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) System.Windows.Forms.Cursor.Current = Cursors.Default; // メッセージ - //MessageBox.Show("自動生成完了!"); - MessageBox.Show(this.RM_GetString("FileGenComplete")); + //this.ShowMessage("自動生成完了!"); + this.ShowMessage(this.RM_GetString("FileGenComplete")); } catch (CheckException cex) { - //MessageBox.Show("チェックエラーです:" + cex.Message); - MessageBox.Show(this.RM_GetString("CheckExceptionError") + cex.Message); - + //this.ShowMessage("チェックエラーです:" + cex.Message); + this.ShowMessage(this.RM_GetString("CheckExceptionError") + cex.Message); + return false; } catch (Exception ex) { - //MessageBox.Show("ランタイムエラーです:" + ex.Message); - MessageBox.Show(this.RM_GetString("RuntimeError") + ex.Message); + //this.ShowMessage("ランタイムエラーです:" + ex.Message); + // CUI時は原因調査のためスタック トレースまで出力する。 + this.ShowMessage(this.RM_GetString("RuntimeError") + + (this.IsCui ? ex.ToString() : ex.Message)); + return false; } finally { @@ -3106,6 +3228,8 @@ private void btnDaoAndSqlGen_Click(object sender, EventArgs e) // カーソルを元に戻す System.Windows.Forms.Cursor.Current = Cursors.Default; } + + return true; } #endregion @@ -3138,7 +3262,7 @@ private void GenerateSQLFile(string sqlTemplate, string extension) // 入力テンプレート // STE:SQLテンプレートのEncoding - srSQLTpl = this.OpenSrTemplate(sqlTemplate, (int)cmbSTEncoding.SelectedValue); + srSQLTpl = this.OpenSrTemplate(sqlTemplate, this.genSqlTemplateCodePage); // 出力ファイル swSQLFile = this.OpenSwSQLFile(this.FileName, extension); @@ -3784,17 +3908,17 @@ private void CreateString(string col, string dbType, bool isPK) + " IS NULL</ELSE>" + "</IF>" + "," + "<IF>AND " - + this.EnclosureCharS + col + this.EnclosureCharE + " " + cmbLikeStatement.Text + " " + + this.EnclosureCharS + col + this.EnclosureCharE + " " + this.genLikeStatement + " " + this.ParamSign.ToString() + this.LikeParamHeader + col.Replace(' ', '_') + this.LikeParamFooter; if (chkEscapeToNChar.Checked == true) { //TO_NCHARする場合 - this.DynColsCondition_Like += " ESCAPE TO_NCHAR('" + txtEscapeChar.Text + "')"; + this.DynColsCondition_Like += " ESCAPE TO_NCHAR('" + this.genEscapeChar + "')"; } else { //TO_NCHARしない場合 - this.DynColsCondition_Like += " ESCAPE '" + txtEscapeChar.Text + "'"; + this.DynColsCondition_Like += " ESCAPE '" + this.genEscapeChar + "'"; } this.DynColsCondition_Like += "</IF>" + ","; @@ -3810,7 +3934,7 @@ private void CreateString(string col, string dbType, bool isPK) "<IF>AND " + this.EnclosureCharS + col + this.EnclosureCharE + " LIKE " + this.ParamSign.ToString() + this.LikeParamHeader + col.Replace(' ', '_') + this.LikeParamFooter - + " ESCAPE '" + txtEscapeChar.Text + "' " + "</IF>" + ","; + + " ESCAPE '" + this.genEscapeChar + "' " + "</IF>" + ","; } } else diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Program.cs b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Program.cs index 31ef75569..ee4c29448 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Program.cs +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/Program.cs @@ -33,14 +33,18 @@ //* and replaced to this method wherever hard coded values. //* Also Added code to get the Culture information from app.config file. //* 2018/10/29 西野 大介 NETCOREAPP対応で、configの初期化 +//* 2026/07/31 玄人 幸道 CUI起動(/CUI)とヘルプ(/HELP)を追加 //********************************************************************************** using System; +using System.Collections.Generic; using System.Threading; using System.Resources; using System.Globalization; +using System.Runtime.InteropServices; using System.Windows.Forms; +using Touryo.Infrastructure.Public.Str; using Touryo.Infrastructure.Public.Util; namespace DaoGen_Tool @@ -48,6 +52,24 @@ namespace DaoGen_Tool /// <summary>アプリケーションのメイン エントリ ポイント</summary> static class Program { + /// <summary>CUI(非対話)で起動しているか</summary> + private static bool _isCui = false; + + #region コンソール制御 + + /// <summary>親プロセスのコンソールにアタッチする</summary> + /// <param name="dwProcessId">-1 で親プロセス</param> + /// <returns>成否</returns> + [DllImport("kernel32.dll")] + private static extern bool AttachConsole(int dwProcessId); + + /// <summary>コンソールをデタッチする</summary> + /// <returns>成否</returns> + [DllImport("kernel32.dll")] + private static extern bool FreeConsole(); + + #endregion + /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> @@ -73,13 +95,425 @@ static void Main() Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(strDefaultCulture); } - Application.Run(new Form1()); + // コマンドライン引数を取得する(キーは大文字化される)。 + List<string> valsLst; + Dictionary<string, string> argsDic; + StringVariableOperator.GetCommandArgs('/', out argsDic, out valsLst); + + // 起動の切り替え + if (argsDic.ContainsKey("/HELP")) + { + // ヘルプ + Program.AttachConsole(-1); + Program.WriteHelp(); + Program.FreeConsole(); + } + else if (argsDic.ContainsKey("/CUI")) + { + // CUI起動(非対話) + Program._isCui = true; + Program.AttachConsole(-1); + try + { + Environment.ExitCode = Program.RunAsCui(argsDic); + } + catch (Exception cuiEx) + { + Console.WriteLine("エラー:" + cuiEx.ToString()); + Environment.ExitCode = 2; + } + Program.FreeConsole(); + } + else + { + // GUI起動 + Application.Run(new Form1()); + } } catch (Exception ex) { - MessageBox.Show(RM_GetString("EntryPoint") + ex.Message); + if (Program._isCui) + { + // CUI起動時は MessageBox で停止させない。 + Console.WriteLine(RM_GetString("EntryPoint") + ex.ToString()); + Environment.ExitCode = 2; + } + else + { + MessageBox.Show(RM_GetString("EntryPoint") + ex.Message); + } + } + } + + #region CUI + + /// <summary>ヘルプを標準出力に表示する</summary> + private static void WriteHelp() + { + Console.WriteLine(""); + Console.WriteLine("DaoGen_Tool(D層自動生成ツール/墨壺)"); + Console.WriteLine(""); + Console.WriteLine(" 引数なし GUIで起動します。"); + Console.WriteLine(" /HELP このヘルプを表示します。"); + Console.WriteLine(" /CUI CUI(非対話)で生成処理を実行します。"); + Console.WriteLine(""); + Console.WriteLine("</CUI 時の共通引数>"); + Console.WriteLine(""); + Console.WriteLine(" /MODE <DAODEFGEN|DAOSQLGEN> 実行する処理(既定:DAOSQLGEN)"); + Console.WriteLine(" DAODEFGEN DBのスキーマから、D層定義情報ファイル(*.csv)を生成"); + Console.WriteLine(" DAOSQLGEN D層定義情報ファイルから、Dao・DTO・SQL を生成"); + Console.WriteLine(""); + Console.WriteLine("</MODE DAODEFGEN 時の引数>"); + Console.WriteLine(""); + Console.WriteLine(" 必須"); + Console.WriteLine(" /OUTPUT <path> 出力先ファイル(*.csv)"); + Console.WriteLine(""); + Console.WriteLine(" 任意"); +#if NETCOREAPP + Console.WriteLine(" /DAP <SQL|ODB|ODP|MCN|NPS> データ プロバイダ(既定:SQL)"); +#else + Console.WriteLine(" /DAP <SQL|OLE|ODB|ODP|MCN> データ プロバイダ(既定:SQL)"); +#endif + Console.WriteLine(" /CONNSTR <string> 接続文字列"); + Console.WriteLine(" (既定:設定ファイルの ConnectionString_*)"); + Console.WriteLine(" /TABLES <name,name,...> 生成対象(既定:全テーブル・ビュー)"); + Console.WriteLine(" /EXCLUDETABLES <name,name,...> 生成対象から除外"); + Console.WriteLine(" /PRIMARYKEYS <T1:C1|C2,T2:C3> 主キー(DBから取得できない場合に指定)"); + Console.WriteLine(" /CODEPAGE <n> 出力のコード ページ(既定:65001)"); + Console.WriteLine(""); + Console.WriteLine("</MODE DAOSQLGEN 時の引数>"); + Console.WriteLine(""); + Console.WriteLine(" 必須"); + Console.WriteLine(" /DAODEF <path> D層定義情報ファイル(*.csv)へのパス"); + Console.WriteLine(" /TEMPLATE <path> テンプレート ファイルのルート フォルダ"); + Console.WriteLine(" /OUTPUT <path> 出力先フォルダ"); + Console.WriteLine(""); + Console.WriteLine(" 任意"); + Console.WriteLine(" /DAP <SQL|OLE|ODB|ODP|DB2|MCN|NPS> データ プロバイダ(既定:SQL)"); + Console.WriteLine(" /LANG <CS|VB> 生成言語(既定:CS)"); + Console.WriteLine(" /ENTITY エンティティ(DTO)を生成"); + Console.WriteLine(" /TYPEDDATASET 型付きデータセットを生成"); + Console.WriteLine(" /TABLEMAINTENANCE テーブル メンテナンス画面を生成"); + Console.WriteLine(" /ONLYDTO DTOのみ生成(Daoを生成しない)"); + Console.WriteLine(" /ONLYTABLEMAINTENANCE メンテ画面のみ生成"); + Console.WriteLine(" /NOHEADER 定義ファイルの1行目をヘッダとして扱わない"); + Console.WriteLine(" /ESCAPECHAR <c> エスケープ文字(ODP時は1文字必須)"); + Console.WriteLine(" /TSCOLNAME <name> タイム スタンプ列名"); + Console.WriteLine(" /TSUPDMETHOD <method> タイム スタンプの更新方法"); + Console.WriteLine(" /FAMILYNAME <name> 作成者(姓)"); + Console.WriteLine(" (既定:設定ファイルの FamilyName)"); + Console.WriteLine(" /PERSONALNAME <name> 作成者(名)"); + Console.WriteLine(" (既定:設定ファイルの PersonalName)"); + Console.WriteLine(" /XMLENCODING <name> SQL(XML)のエンコーディング(既定:utf-8)"); + Console.WriteLine(" /CODEPAGE <n> クラス ファイルのコード ページ(既定:65001)"); + Console.WriteLine(""); + Console.WriteLine("<終了コード> 0:成功 / 1:引数エラー / 2:生成エラー"); + Console.WriteLine(""); + Console.WriteLine("<パス区切りの注意>"); + Console.WriteLine(" コマンドライン解析では \\ をエスケープ文字として扱うため、"); + Console.WriteLine(" パスの区切りには / を使用してください(\\\\ でも可)。"); + Console.WriteLine(" OK : /OUTPUT \"C:/temp/out\""); + Console.WriteLine(" OK : /OUTPUT \"C:\\\\temp\\\\out\""); + Console.WriteLine(" NG : /OUTPUT \"C:\\temp\\out\" ← \\ が消えます"); + Console.WriteLine(""); + Console.WriteLine("</PRIMARYKEYS の書式>"); + Console.WriteLine(" テーブル名 : 主キー列名 | 主キー列名 ... を、カンマ区切りで複数指定します。"); + Console.WriteLine(" 主キー情報をDBMSから取得できないデータ プロバイダ"); + Console.WriteLine(" (ODBC・OLEDB・MySQL・PostgreSQL)で使用します。"); + Console.WriteLine(" 例 : /PRIMARYKEYS \"Orders:OrderID,OrderDetails:OrderID|ProductID\""); + Console.WriteLine(""); + } + + /// <summary>コマンドライン引数から値を取得する</summary> + /// <param name="argsDic">コマンドライン引数</param> + /// <param name="key">キー("/XXX")</param> + /// <param name="defaultValue">既定値</param> + /// <returns>値</returns> + private static string GetArg(Dictionary<string, string> argsDic, string key, string defaultValue) + { + if (argsDic.ContainsKey(key) && !string.IsNullOrEmpty(argsDic[key])) + { + return argsDic[key]; + } + return defaultValue; + } + + /// <summary>コマンドライン引数から、カンマ区切りの値を配列で取得する</summary> + /// <param name="argsDic">コマンドライン引数</param> + /// <param name="key">キー("/XXX")</param> + /// <returns>値の配列(指定が無い場合は空配列)</returns> + private static string[] GetArrayArg(Dictionary<string, string> argsDic, string key) + { + string value = Program.GetArg(argsDic, key, ""); + + if (string.IsNullOrEmpty(value)) + { + return new string[0]; + } + + List<string> valueLst = new List<string>(); + foreach (string temp in value.Split(',')) + { + if (temp.Trim() != "") + { + valueLst.Add(temp.Trim()); + } + } + + return valueLst.ToArray(); + } + + /// <summary>CUI(非対話)で生成処理を実行する</summary> + /// <param name="argsDic">コマンドライン引数</param> + /// <returns>終了コード(0:成功 / 1:引数エラー / 2:生成エラー)</returns> + private static int RunAsCui(Dictionary<string, string> argsDic) + { + // 実行する処理の切り替え + string mode = Program.GetArg(argsDic, "/MODE", "DAOSQLGEN").ToUpper(); + + if (mode == "DAODEFGEN") + { + // DBのスキーマ → D層定義情報ファイル + return Program.RunDaoDefinitionGen(argsDic); + } + else if (mode == "DAOSQLGEN") + { + // D層定義情報ファイル → Dao・DTO・SQL + return Program.RunDaoAndSqlGen(argsDic); + } + else + { + Console.WriteLine("引数エラー:/MODE には DAODEFGEN または DAOSQLGEN を指定してください。"); + Console.WriteLine("使用方法は /HELP で確認してください。"); + return 1; + } + } + + /// <summary>CUI(非対話)で、DBのスキーマからD層定義情報ファイルを生成する</summary> + /// <param name="argsDic">コマンドライン引数</param> + /// <returns>終了コード(0:成功 / 1:引数エラー / 2:生成エラー)</returns> + private static int RunDaoDefinitionGen(Dictionary<string, string> argsDic) + { + DaoDefinitionOptions opt = new DaoDefinitionOptions(); + + // 出力先(必須) + opt.OutputFilePath = Program.GetArg(argsDic, "/OUTPUT", ""); + + if (string.IsNullOrEmpty(opt.OutputFilePath)) + { + Console.WriteLine("引数エラー:/OUTPUT は必須です。"); + Console.WriteLine("使用方法は /HELP で確認してください。"); + return 1; + } + + // データ プロバイダ + opt.Dap = Program.GetArg(argsDic, "/DAP", "SQL").ToUpper(); + + if (!Program.IsSupportedDap(opt.Dap)) + { + Console.WriteLine("引数エラー:データ プロバイダ[" + + opt.Dap + "]は、このビルドではサポートされていません。"); + Console.WriteLine("使用方法は /HELP で確認してください。"); + return 1; + } + + // 接続文字列(省略時は設定ファイルの値を使用する) + opt.ConnectionString = Program.GetArg(argsDic, "/CONNSTR", ""); + + if (string.IsNullOrEmpty(opt.ConnectionString)) + { + string configKey = Program.GetConnectionStringKey(opt.Dap); + + if (configKey == "") + { + Console.WriteLine("引数エラー:/DAP には SQL, OLE, ODB, ODP, DB2, MCN, NPS を指定してください。"); + return 1; + } + + opt.ConnectionString = GetConfigParameter.GetConfigValue(configKey); + + if (string.IsNullOrEmpty(opt.ConnectionString)) + { + Console.WriteLine("引数エラー:/CONNSTR が指定されておらず、" + + "設定ファイルにも " + configKey + " がありません。"); + return 1; + } + } + + // 生成対象 + opt.Tables = Program.GetArrayArg(argsDic, "/TABLES"); + opt.ExcludeTables = Program.GetArrayArg(argsDic, "/EXCLUDETABLES"); + + // 主キー("T1:C1|C2,T2:C3" 形式) + foreach (string temp in Program.GetArrayArg(argsDic, "/PRIMARYKEYS")) + { + int index = temp.IndexOf(':'); + + if (index <= 0 || index == temp.Length - 1) + { + Console.WriteLine("引数エラー:/PRIMARYKEYS の書式が不正です(" + temp + ")。"); + Console.WriteLine("使用方法は /HELP で確認してください。"); + return 1; + } + + opt.PrimaryKeys[temp.Substring(0, index).Trim()] + = temp.Substring(index + 1).Split('|'); + } + + // エンコーディング + int codePage; + if (!int.TryParse(Program.GetArg(argsDic, "/CODEPAGE", "65001"), out codePage)) + { + Console.WriteLine("引数エラー:/CODEPAGE には数値を指定してください。"); + return 1; + } + opt.CodePage = codePage; + + // 生成処理の呼び出し + // ※ Form1 は表示しない。UIコントロールは初期化のみ行われる。 + Form1 form1 = new Form1(); + form1.IsCui = true; + + Console.WriteLine("生成を開始します。"); + bool result = form1.DaoDefinitionGen(opt); + + if (result) + { + Console.WriteLine("生成が完了しました。"); + return 0; + } + else + { + Console.WriteLine("生成に失敗しました。"); + return 2; + } + } + + /// <summary>DBに接続できるデータ プロバイダか(このビルドでサポートされるか)を判定する</summary> + /// <param name="dap">データ プロバイダ</param> + /// <returns>サポートされる場合 true</returns> + /// <remarks> + /// DB2・HiRDBは、両ビルドともコードがコメントアウトされているためサポートされない。 + /// ※ /MODE DAOSQLGEN はDBに接続しない(テンプレートの選択にのみ使用する)ため、この判定は行わない。 + /// </remarks> + private static bool IsSupportedDap(string dap) + { + switch (dap) + { + case "SQL": + case "ODB": + case "ODP": + case "MCN": + return true; +#if NETCOREAPP + // PostgreSQLは、NETCOREAPPでのみサポートされる。 + case "NPS": + return true; +#else + // OLEDBは、NETCOREAPPではサポートされない。 + case "OLE": + return true; +#endif + default: + return false; } } + + /// <summary>データ プロバイダに対応する、接続文字列の設定キーを取得する</summary> + /// <param name="dap">データ プロバイダ</param> + /// <returns>設定キー(対応しないデータ プロバイダの場合は空文字)</returns> + private static string GetConnectionStringKey(string dap) + { + switch (dap) + { + case "SQL": return "ConnectionString_SQL"; + case "OLE": return "ConnectionString_OLE"; + case "ODB": return "ConnectionString_ODBC"; + case "ODP": return "ConnectionString_ODP"; + case "DB2": return "ConnectionString_DB2"; + case "MCN": return "ConnectionString_MCN"; + case "NPS": return "ConnectionString_NPS"; + default: return ""; + } + } + + /// <summary>CUI(非対話)で、D層定義情報ファイルから Dao・DTO・SQL を生成する</summary> + /// <param name="argsDic">コマンドライン引数</param> + /// <returns>終了コード(0:成功 / 1:引数エラー / 2:生成エラー)</returns> + private static int RunDaoAndSqlGen(Dictionary<string, string> argsDic) + { + DaoGenOptions opt = new DaoGenOptions(); + + // 入出力パス(必須) + opt.DaoDefinitionFilePath = Program.GetArg(argsDic, "/DAODEF", ""); + opt.TemplateRootPath = Program.GetArg(argsDic, "/TEMPLATE", ""); + opt.OutputPath = Program.GetArg(argsDic, "/OUTPUT", ""); + + if (string.IsNullOrEmpty(opt.DaoDefinitionFilePath) + || string.IsNullOrEmpty(opt.TemplateRootPath) + || string.IsNullOrEmpty(opt.OutputPath)) + { + Console.WriteLine("引数エラー:/DAODEF, /TEMPLATE, /OUTPUT は必須です。"); + Console.WriteLine("使用方法は /HELP で確認してください。"); + return 1; + } + + // データ プロバイダ・言語 + opt.Dap = Program.GetArg(argsDic, "/DAP", "SQL").ToUpper(); + opt.IsCSharp = (Program.GetArg(argsDic, "/LANG", "CS").ToUpper() != "VB"); + + // 生成対象 + opt.CreateEntity = argsDic.ContainsKey("/ENTITY"); + opt.CreateTypedDataSet = argsDic.ContainsKey("/TYPEDDATASET"); + opt.CreateTableMaintenance = argsDic.ContainsKey("/TABLEMAINTENANCE"); + opt.OnlyDTO = argsDic.ContainsKey("/ONLYDTO"); + opt.OnlyTableMaintenance = argsDic.ContainsKey("/ONLYTABLEMAINTENANCE"); + + // 生成オプション + opt.DaoDefinitionHeader = !argsDic.ContainsKey("/NOHEADER"); + opt.EscapeChar = Program.GetArg(argsDic, "/ESCAPECHAR", ""); + opt.TimeStampColName = Program.GetArg(argsDic, "/TSCOLNAME", ""); + opt.TimeStampUpdMethod = Program.GetArg(argsDic, "/TSUPDMETHOD", ""); + // 作成者(省略時は設定ファイルの値を使用する。GUIのForm2_Loadと同じ挙動。) + opt.FamilyName = Program.GetArg(argsDic, "/FAMILYNAME", + GetConfigParameter.GetConfigValue("FamilyName") ?? ""); + opt.PersonalName = Program.GetArg(argsDic, "/PERSONALNAME", + GetConfigParameter.GetConfigValue("PersonalName") ?? ""); + + // エンコーディング + opt.XmlEncoding = Program.GetArg(argsDic, "/XMLENCODING", "utf-8"); + int codePage; + if (!int.TryParse(Program.GetArg(argsDic, "/CODEPAGE", "65001"), out codePage)) + { + Console.WriteLine("引数エラー:/CODEPAGE には数値を指定してください。"); + return 1; + } + opt.ClassFileCodePage = codePage; + + // 生成処理の呼び出し + // ※ Form2 は表示しない。UIコントロールは初期化のみ行われる。 + Form2 form2 = new Form2(); + form2.IsCui = true; + form2.Init(opt.Dap); + // Form2_Load は表示時にしか発火しないため、設定の読み込みを明示的に呼ぶ。 + form2.LoadSettingsFromConfig(); + + Console.WriteLine("生成を開始します。"); + bool result = form2.DaoAndSqlGen(opt); + + if (result) + { + Console.WriteLine("生成が完了しました。"); + return 0; + } + else + { + Console.WriteLine("生成に失敗しました。"); + return 2; + } + } + + #endregion /// <summary>This Method gets the string values from resource file based on the key passed</summary> private static string RM_GetString(string key) diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/README.md b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/README.md new file mode 100644 index 000000000..8de63ce84 --- /dev/null +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/README.md @@ -0,0 +1,163 @@ +# DaoGen_Tool(D層自動生成ツール/墨壺)— CLI + +DB のスキーマから、D層の定義情報・Dao クラス・DTO・SQL を生成するツール。 +GUI と CUI の両方を持ち、**CUI は非対話**なのでエージェントから実行できる(#508)。 + +本書は**エージェントが実行するため**の情報を記す。 +**引数の一覧は書かない。** `/HELP` を実行すれば得られ、二重管理になるため。 + +--- + +## 1. ヘルプの実行(まずこれを見る) + +```powershell +# net48 +cd root\programs\CS\Frameworks\Tools\DaoGen_Tool\bin\Debug +.\OpenTouryo.DaoGen_Tool.exe /HELP + +# .NET 10 +cd root\programs\CS\Frameworks\Tools\DaoGen_Tool\bin\Debug\net10.0-windows7.0 +.\OpenTouryo.DaoGen_Tool.exe /HELP +``` + +`/HELP` が**引数仕様の一次情報**。次が得られる。 + +- 起動の切り替え(引数なし=GUI、`/HELP`、`/CUI`) +- `/CUI` 時の共通引数(`/MODE <DAODEFGEN|DAOSQLGEN>`) +- モードごとの必須・任意の引数 +- 終了コード +- パス区切りと `/PRIMARYKEYS` の書式 + +**引数を組み立てる前に必ず `/HELP` を実行すること。** 本書の記述より `/HELP` が正である。 + +--- + +## 2. 実行ファイルの場所(`/HELP` からは分からない) + +**アセンブリ名がプロジェクト名と異なる。** `DaoGen_Tool.exe` ではない。 + +| ターゲット | パス(`DaoGen_Tool` からの相対) | +|---|---| +| net48 | `bin\Debug\OpenTouryo.DaoGen_Tool.exe` | +| .NET 10 | `bin\Debug\net10.0-windows7.0\OpenTouryo.DaoGen_Tool.exe` | + +ビルドは既定のバッチで行う(`root\programs\CS` をカレントにして実行)。 + +```powershell +cmd /c "echo. | call 4_Build_Framework_Tool.bat" # net48 +cmd /c "echo. | call 4_Build_Framework_ToolCore.bat" # .NET 10 +``` + +> `1_DeleteDir.bat` は配下の `bin` / `obj` を再帰的に削除する。 +> フル ビルド(`1_BuildAll.ps1`)の後は**再ビルドが必要**なことがある。 + +--- + +## 3. エージェントが踏みやすい罠 + +### 3.1 パスの区切りは `/` にする + +コマンドライン解析(`StringVariableOperator.GetCommandArgs`)は +**`\` をエスケープ文字として扱う**。`\` は消えるため、別のパスとして解釈される。 + +``` +OK : /OUTPUT "C:/temp/out" +OK : /OUTPUT "C:\\temp\\out" +NG : /OUTPUT "C:\temp\out" ← \ が消える +``` + +PowerShell から渡す場合は変換しておく。 + +```powershell +$out = (Join-Path $env:TEMP "daogen/DaoDef.csv").Replace("\", "/") +``` + +> **終了コードでは検出できない。** +> `\` を使っても処理は成功し、**`0` が返る**。 +> ただし出力先が別のパスになるため、指定した場所にファイルが無い。 +> **生成物の存在を必ず確認すること**(5 節)。 + +### 3.2 標準出力は PowerShell のリダイレクトで受ける + +本ツールは `WinExe` で、CUI 時は `AttachConsole(-1)` でコンソールに接続する。 +このため**リダイレクトの方法によって出力が取れない**。 + +| 方法 | 結果 | +|---|---| +| `& $exe /HELP *>&1 \| Out-File $out` | **取れる** | +| `cmd /c "$exe /HELP > $out"` | **取れない**(0 バイト) | + +### 3.3 GUI が開く条件 + +`/HELP` も `/CUI` も無い場合は `Application.Run(new Form1())` になり、 +**画面が開いて応答が返らない**。エージェントは必ずどちらかを付ける。 + +--- + +## 4. 前提 + +### 4.1 接続文字列 + +`/CONNSTR` を省略すると設定ファイルの `ConnectionString_*` を使う。 +`/DAP` の値に対応するキーが選ばれる。 + +| ターゲット | 設定ファイル | +|---|---| +| net48 | `app.config`(`appSettings`) | +| .NET 10 | `appsettings.json`(`appSettings`) | + +いずれも**実行ファイルと同じフォルダ**に配置される。 +`FamilyName` / `PersonalName`(生成物のヘッダに入る作成者名)も同じ場所。 + +### 4.2 テンプレート + +`/MODE DAOSQLGEN` の `/TEMPLATE` にはテンプレートのルート フォルダを渡す。 +リポジトリ内では次の場所にある(`DaoTemplate*.cs` などが平置き)。 + +``` +root/files/tools/DGenTemplates +``` + +### 4.3 DB + +`/MODE DAODEFGEN` は DB のスキーマを読むため、接続できる必要がある。 +リポジトリの検証では SQL Server の Northwind を使っている。 + +--- + +## 5. 実行例(2 モードを連続して使う) + +`DAODEFGEN` が出力した定義 CSV を `DAOSQLGEN` の入力に使う。 + +```powershell +$exe = "...\bin\Debug\net10.0-windows7.0\OpenTouryo.DaoGen_Tool.exe" +$work = "C:/temp/daogen" +$csv = "$work/DaoDef.csv" +$tmpl = "C:/OpenTouryo/root/files/tools/DGenTemplates" + +# DB のスキーマ → D層定義情報(*.csv) +& $exe /CUI /MODE DAODEFGEN /OUTPUT $csv /DAP SQL /TABLES "Shippers,Orders" + +# D層定義情報 → Dao・DTO・SQL +& $exe /CUI /MODE DAOSQLGEN /DAODEF $csv /TEMPLATE $tmpl /OUTPUT "$work/gen" ` + /DAP SQL /LANG CS /ENTITY +``` + +**判定は終了コードと生成物の両方で行う。** +終了コードの意味は `/HELP` を参照。生成物は次を確認するとよい。 + +- `DAODEFGEN` … 定義 CSV に対象テーブルが並んでいること +- `DAOSQLGEN` … Dao(`.cs`)・動的 SQL(`.xml`)・静的 SQL(`.sql`) が揃っていること + +--- + +## 6. 疎通確認との関係 + +`3_SmokeTest.ps1` が上記 3 つ(`/HELP`・`DAODEFGEN`・`DAOSQLGEN`)を +net48 / .NET 10 の両方で実行している。 +**動く引数の組み合わせを確かめたい場合は、そちらの定義が参考になる。** + +詳細は [`SMOKETEST.md`](../../../../SMOKETEST.md)。 + +なお **GUI の確認は手作業**として残している([`RELEASE.md`](../../../../RELEASE.md))。 +CUI で確認できるのは生成ロジックまでで、画面の動作は含まない。 diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/app.config b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/app.config index 3ca5be79d..2a857af9b 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/app.config +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/app.config @@ -24,7 +24,7 @@ <!-- ★入力項目(テンプレート) --> <!-- Daoクラス テンプレート ファイル(拡張子を除く) --> - <add key="DaoTemplateFileName" value="DaoTemplate" /> + <add key="DaoTemplateFileName" value="DaoTemplate3" /> <!-- Entityクラス テンプレート ファイル(拡張子を除く) --> <add key="EntityTemplateFileName" value="EntityTemplate" /> diff --git a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/appsettings.json b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/appsettings.json index 11a391659..c5ea90da1 100644 --- a/root/programs/CS/Frameworks/Tools/DaoGen_Tool/appsettings.json +++ b/root/programs/CS/Frameworks/Tools/DaoGen_Tool/appsettings.json @@ -22,7 +22,7 @@ // ★入力項目(テンプレート) // Daoクラス テンプレート ファイル(拡張子を除く) - "DaoTemplateFileName": "DaoTemplate", + "DaoTemplateFileName": "DaoTemplate3", // Entityクラス テンプレート ファイル(拡張子を除く) "EntityTemplateFileName": "EntityTemplate", diff --git a/root/programs/CS/NuGet/Symbol_DamManagedOdp.nuspec b/root/programs/CS/NuGet/Symbol_DamManagedOdp.nuspec index 694e72056..3302fabb5 100644 --- a/root/programs/CS/NuGet/Symbol_DamManagedOdp.nuspec +++ b/root/programs/CS/NuGet/Symbol_DamManagedOdp.nuspec @@ -3,7 +3,7 @@ <metadata> <id>Touryo.Infrastructure.Public.Db.DamManagedOdp</id> <title>OpenTouryo.DamManagedOdp - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,11 +17,11 @@ OpenTouryo Open棟梁 - + - - + + @@ -33,9 +33,9 @@ - - - + + + diff --git a/root/programs/CS/NuGet/Symbol_DamMySQL.nuspec b/root/programs/CS/NuGet/Symbol_DamMySQL.nuspec index 11fd720f3..4e9c351db 100644 --- a/root/programs/CS/NuGet/Symbol_DamMySQL.nuspec +++ b/root/programs/CS/NuGet/Symbol_DamMySQL.nuspec @@ -3,7 +3,7 @@ Touryo.Infrastructure.Public.Db.DamMySQL OpenTouryo.DamMySQL - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,12 +17,12 @@ OpenTouryo Open棟梁 - + - - + + @@ -34,9 +34,9 @@ - - - + + + diff --git a/root/programs/CS/NuGet/Symbol_DamPstGrS.nuspec b/root/programs/CS/NuGet/Symbol_DamPstGrS.nuspec index b9230f3ec..58e0f342b 100644 --- a/root/programs/CS/NuGet/Symbol_DamPstGrS.nuspec +++ b/root/programs/CS/NuGet/Symbol_DamPstGrS.nuspec @@ -3,7 +3,7 @@ Touryo.Infrastructure.Public.Db.DamPstGrS OpenTouryo.DamPstGrS - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -16,8 +16,8 @@ OpenTouryo Open棟梁 - - + + @@ -25,9 +25,9 @@ - - - + + + diff --git a/root/programs/CS/NuGet/Symbol_Framework.RichClient.nuspec b/root/programs/CS/NuGet/Symbol_Framework.RichClient.nuspec index f96f7edfa..8c150c757 100644 --- a/root/programs/CS/NuGet/Symbol_Framework.RichClient.nuspec +++ b/root/programs/CS/NuGet/Symbol_Framework.RichClient.nuspec @@ -3,7 +3,7 @@ Touryo.Infrastructure.Framework.RichClient OpenTouryo.Framework.RichClient - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,12 +17,12 @@ OpenTouryo Open棟梁 - - + + - - - + + + @@ -33,9 +33,9 @@ - - - + + + diff --git a/root/programs/CS/NuGet/Symbol_Framework.nuspec b/root/programs/CS/NuGet/Symbol_Framework.nuspec index 051a0c220..b1a8be155 100644 --- a/root/programs/CS/NuGet/Symbol_Framework.nuspec +++ b/root/programs/CS/NuGet/Symbol_Framework.nuspec @@ -3,7 +3,7 @@ Touryo.Infrastructure.Framework OpenTouryo.Framework - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,22 +17,20 @@ OpenTouryo Open棟梁 - - + + - - - + + + - - @@ -44,10 +42,10 @@ - - - - + + + + diff --git a/root/programs/CS/NuGet/Symbol_Public.Security.nuspec b/root/programs/CS/NuGet/Symbol_Public.Security.nuspec index b9c62e1e4..5c6b1de9f 100644 --- a/root/programs/CS/NuGet/Symbol_Public.Security.nuspec +++ b/root/programs/CS/NuGet/Symbol_Public.Security.nuspec @@ -1,9 +1,9 @@ - + Touryo.Infrastructure.Public.Security OpenTouryo.Public.Security - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,19 +17,15 @@ OpenTouryo Open棟梁 - + - - - + + - - - - + @@ -40,9 +36,9 @@ - - - + + + diff --git a/root/programs/CS/NuGet/Symbol_Public.nuspec b/root/programs/CS/NuGet/Symbol_Public.nuspec index b8d47556f..348d51e74 100644 --- a/root/programs/CS/NuGet/Symbol_Public.nuspec +++ b/root/programs/CS/NuGet/Symbol_Public.nuspec @@ -3,7 +3,7 @@ Touryo.Infrastructure.Public OpenTouryo.Public - 3.0.0 + $version$ OSS Consortium .net subcommittee daisukenishino77 Apache-2.0 @@ -17,15 +17,13 @@ OpenTouryo Open棟梁 - - + - - - + + @@ -34,8 +32,6 @@ - - @@ -48,10 +44,10 @@ - - - - + + + + diff --git a/root/programs/CS/NuGet/T_NuGetPack.bat b/root/programs/CS/NuGet/T_NuGetPack.bat index 28bc3fe9e..cdff71cd4 100644 --- a/root/programs/CS/NuGet/T_NuGetPack.bat +++ b/root/programs/CS/NuGet/T_NuGetPack.bat @@ -2,8 +2,8 @@ @echo off xcopy /E /Y "..\Frameworks\Infrastructure\Build_net48" "in\net48" -xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore80\net8.0" "in\net8.0" -xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore80\net8.0-windows" "in\net8.0-windows" +xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore100\net10.0" "in\net10.0" +xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore100\net10.0-windows7.0" "in\net10.0-windows" "..\..\nuget.exe" pack T_Symbol_Public.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg pause diff --git a/root/programs/CS/NuGet/T_Symbol_Public.nuspec b/root/programs/CS/NuGet/T_Symbol_Public.nuspec index d607d70ea..020c41057 100644 --- a/root/programs/CS/NuGet/T_Symbol_Public.nuspec +++ b/root/programs/CS/NuGet/T_Symbol_Public.nuspec @@ -17,15 +17,13 @@ - - + - - - + + @@ -34,8 +32,6 @@ - - @@ -48,10 +44,10 @@ - - - - + + + + diff --git a/root/programs/CS/NuGet/_NuGetPack.bat b/root/programs/CS/NuGet/_NuGetPack.bat index 2090f13bb..28c02652e 100644 --- a/root/programs/CS/NuGet/_NuGetPack.bat +++ b/root/programs/CS/NuGet/_NuGetPack.bat @@ -1,16 +1,39 @@ setlocal @echo off +chcp 65001 >nul + +@rem -------------------------------------------------- +@rem バージョン番号を Directory.Build.props から取得する。 +@rem (nuspec 側は $version$ トークンのままにしてあり、 +@rem  バージョンの定義箇所を1か所に集約している。) +@rem -------------------------------------------------- +set OT_PROPS=..\Frameworks\Infrastructure\Directory.Build.props +set OT_VERSION= + +for /f "usebackq delims=" %%v in ( + `powershell -NoProfile -ExecutionPolicy Bypass -Command "([xml](Get-Content '%OT_PROPS%' -Raw)).Project.PropertyGroup.OpenTouryoVersion"` +) do set OT_VERSION=%%v + +if not defined OT_VERSION ( + echo [ERROR] %OT_PROPS% から OpenTouryoVersion を取得できませんでした。 + pause + exit /b 1 +) + +echo -------------------------------------------------- +echo OpenTouryoVersion = %OT_VERSION% +echo -------------------------------------------------- xcopy /E /Y "..\Frameworks\Infrastructure\Build_net48" "in\net48" -xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore80\net8.0" "in\net8.0" -xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore80\net8.0-windows" "in\net8.0-windows" +xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore100\net10.0" "in\net10.0" +xcopy /E /Y "..\Frameworks\Infrastructure\Build_netcore100\net10.0-windows7.0" "in\net10.0-windows" -"..\..\nuget.exe" pack Symbol_Public.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_Public.Security.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_Framework.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_Framework.RichClient.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_DamManagedOdp.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_DamPstGrS.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg -"..\..\nuget.exe" pack Symbol_DamMySQL.nuspec -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_Public.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_Public.Security.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_Framework.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_Framework.RichClient.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_DamManagedOdp.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_DamPstGrS.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg +"..\..\nuget.exe" pack Symbol_DamMySQL.nuspec -Properties version=%OT_VERSION% -OutputDirectory "out\sp" -Symbols -SymbolPackageFormat snupkg pause diff --git "a/root/programs/CS/NuGet/_\346\211\213\351\240\206\343\201\256\350\252\254\346\230\216.txt" "b/root/programs/CS/NuGet/_\346\211\213\351\240\206\343\201\256\350\252\254\346\230\216.txt" index 63095ac30..f98500c25 100644 --- "a/root/programs/CS/NuGet/_\346\211\213\351\240\206\343\201\256\350\252\254\346\230\216.txt" +++ "b/root/programs/CS/NuGet/_\346\211\213\351\240\206\343\201\256\350\252\254\346\230\216.txt" @@ -33,3 +33,7 @@   リリース・エンジニアリング - Open 棟梁 Wiki   https://opentouryo.osscons.jp/index.php?%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%BB%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0   ※ NuGet利用リポジトリのNuGet参照の貼り直し。 + +以下とも重複があるので最終的には統合を行う。 +https://github.com/OpenTouryoProject/OpenTouryo/wiki/HowToCreateOpenTouryoNuGetPackages.ja +リリース・エンジニアリング - Open 棟梁 Wiki も 新設した RELEASE.md との乖離がある。 diff --git "a/root/programs/CS/NuGet/in/net8.0-windows/net8.0-windows\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" "b/root/programs/CS/NuGet/in/net10.0-windows/net10.0-windows\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" similarity index 100% rename from "root/programs/CS/NuGet/in/net8.0-windows/net8.0-windows\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" rename to "root/programs/CS/NuGet/in/net10.0-windows/net10.0-windows\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" diff --git "a/root/programs/CS/NuGet/in/net8.0/net8.0\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" "b/root/programs/CS/NuGet/in/net10.0/net10.0\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" similarity index 100% rename from "root/programs/CS/NuGet/in/net8.0/net8.0\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" rename to "root/programs/CS/NuGet/in/net10.0/net10.0\343\201\256dll\343\202\222\351\205\215\347\275\256.txt" diff --git a/root/programs/CS/Samples/ANALYSIS.md b/root/programs/CS/Samples/ANALYSIS.md new file mode 100644 index 000000000..acc376b6f --- /dev/null +++ b/root/programs/CS/Samples/ANALYSIS.md @@ -0,0 +1,375 @@ +# ANALYSIS.md — Open棟梁 サンプル アプリ(CS/Samples)コード分析 + +対象: `root/programs/CS/Samples`(**.NET Framework 4.8 専用**) / ブランチ: `develop` +最終更新: 2026-07-31 + +本書は **コーディング・エージェントが本ディレクトリで作業する際の Context** を目的とする。 +フレームワーク本体の分析は `../Frameworks/ANALYSIS.md` を、 +.NET (Core) 版サンプルは `../Samples4NetCore/ANALYSIS.md` を参照。 + +--- + +## 1. これは何か + +Open棟梁フレームワークの **使い方を示すサンプル兼テンプレート**。 +実務では「該当するサンプルをコピーして中身を書き換える」のが標準的な使い方であり、 +コード中に **`// テスト用サンプルなので、必要に応じて流用 or 削除して下さい。`** という +断り書きが全ファイルに入っている。つまり **これらは「消して良い雛形」として書かれている**。 + +同時に **フレームワークの動作確認(テストベッド)** も兼ねており、 +特に `WebForms_Sample` は P層機能(画面遷移制御・二重送信検出・ダイアログ等)の網羅テストになっている。 + +**全プロジェクトが `net48`(旧形式 csproj)。** SDK 形式は 1 つもない。 + +--- + +## 2. 前提条件(これを満たさないと動かない) + +### 2-1. リポジトリを `C:\root\` に配置する + +**サンプルの設定ファイルは `C:\root\files\resource\...` という絶対パスを直書きしている。** + +```xml + + +``` + +`root/Readme.ja.md` の手順どおり、リポジトリの `root` 配下を `C:\root\` に展開する必要がある。 +本リポジトリのチェックアウト先が `C:\OpenTouryo\root\` の場合、**`C:\root\files` を別途用意しないと +実行時に定義ファイルが見つからず落ちる**(ビルドは通る)。 + +> 補足: 分析時点のこの環境には `C:\root\files\` が存在し、`Log / MultiPurposeAuthSite / Sql / Test / X509 / Xml` が配置済み。 + +### 2-2. データベース + +- **SQL Server の Northwind データベース**が既定(`app.config` の `ConnectionString_SQL`)。 +- `Bat_sample/RerunnableBatch_sample*` は追加で **`ORDERS2` テーブル**が必要 + (各 `readme.txt` 記載。`CREATE ORDERS2.sql` を実行し、実行の都度 `DELETE FROM ORDERS2`)。 +- SQL Server 以外は `C:\root\files\resource\Sql\[DBMS名]\TestTable.txt` でテスト表を作成。 +- 接続文字列は `localhost` / `sa` / `seigi@123` 等の **サンプル値**がリポジトリに直書きされている + (公開 OSS のサンプル設定であり実資格情報ではない。流用時は必ず差し替える)。 + +### 2-3. フレームワークを先にビルドしておく + +**全サンプルが `Frameworks\Infrastructure\Build\` の DLL を `HintPath` で参照する。** + +```xml +..\..\..\Frameworks\Infrastructure\Build\OpenTouryo.Business.dll +``` + +`Build\` は `4_Build_CopyAssemblies.bat`(`Build_net48` → `Build\` を xcopy)が作るディレクトリ。 +したがって **ビルド順は厳守**: + +``` +2_Build_NuGet_net48.bat → Public / Framework / Public.Security / Dam* +3_Build_Business_net48.bat → Business +4_Build_CopyAssemblies.bat → Build_net48 を Build\ へコピー ★これを飛ばすと全滅 +5〜10_Build_*_sample.bat → 各サンプル +``` + +CS/VB 合わせて **42 プロジェクト**がこの `Build\` を参照している。 + +--- + +## 3. サンプル一覧 + +| ディレクトリ | 種別 | 概要 | +|---|---|---| +| `2CS_sample/2CSClientWin_sample` | WinForms | **2層C/S の基本形**。Splash → Login → Form1 | +| `2CS_sample/2CSClientWPF_sample` | WPF | 同上の WPF 版 | +| `2CS_sample/GenDaoAndBatUpd_sample` | WinForms | **自動生成Dao(DaoGen_Tool 出力)とバッチ更新**の利用例 | +| `2CS_sample/TimeStamp_sample` | WinForms | **タイムスタンプ(楽観排他)対応**の自動生成Dao | +| `2CS_sample/CustCtrl_sample` | WinForms | **カスタム コントロール**(`WinCustomTextBox` 等)のデザインタイム プロパティ検証。`Readme.txt` が事実上の仕様書 | +| `2CS_sample/AsyncEvent_sample` | WinForms/WPF | **非同期イベント処理**。`test-winx2&wpfx2.bat` で 4 プロセス起動 | +| `Bat_sample/SimpleBatch_sample` | コンソール | **バッチの最小形**。オンライン処理と同じ流儀 | +| `Bat_sample/RerunnableBatch_sample` | コンソール | リラン可能バッチ。通常のデータアクセス | +| `Bat_sample/RerunnableBatch_sample2` | コンソール | `SQLUtility` + `ExecGenerateSQL` でラウンドトリップ削減 | +| `Bat_sample/RerunnableBatch_sample3` | コンソール | `SQLUtility` で DataTable から Insert 文生成(**静的SQLのみ**) | +| `WS_sample/WSServer_sample` | Library | **サービス側の B/D 層**。ServiceInterface からレイトバインドされる | +| `WS_sample/WSIFType_sample` | Library | WS の I/F 型(引数・戻り値クラス)を**サーバ/クライアント共有**するためのアセンブリ | +| `WS_sample/WSClient_sample/*` | WinForms/WPF | **3層型クライアント**。`CallController` 経由で B層を呼ぶ(4 種) | +| `WS_sample/ASPNETWebService` | — | **README のみ**。実体は別リポジトリ `ResourceServerTemplates` へ移動済み | +| `WebApp_sample/WebForms_Sample` | ASP.NET Web Forms | **最大のサンプル(.aspx 38 画面)**。P層機能の網羅テスト | +| `WebApp_sample/MVC_Sample` | ASP.NET MVC5 | MVC5 + WebAPI 版 | +| `CLI_sample/*` | — | **README のみ(3 件)**。net48 版はドロップ済み(後述) | + +### 存在しないもの / 移動したもの + +- **`CLI_sample` の実体は無い。** `Simple_CLI` は Sharprompt が .NET Framework サポートを終了したため net48 版をドロップ。 + `DAG_Login_CLI` / `LIR_Login_CLI` は `System.CommandLine` の beta 解除待ちで移植保留。 + → **実装は `../Samples4NetCore/Legacy/CLI_sample/` にのみ存在する。** +- **`WS_sample/ASPNETWebService`** は `OpenTouryoProject/ResourceServerTemplates` へ移動。 + +--- + +## 4. 標準的なプロジェクト構成(この形をコピーする) + +``` +XXX_sample/ +├─ Business/LayerB.cs … B層(MyFcBaseLogic 継承、UOC_ メソッド群) +├─ Common/TestParameterValue.cs … 引数クラス(MyParameterValue 継承) +├─ Common/TestReturnValue.cs … 戻り値クラス(MyReturnValue 継承) +├─ Dao/LayerD.cs … D層(MyBaseDao 継承、個別Dao) +├─ Dao/DaoShippers.cs … D層(DaoGen_Tool が生成した自動生成Dao) +├─ Program.cs / Form1.cs … P層(エントリポイント) +├─ MSGDefinition.xml … メッセージ定義 +├─ SPDefinition.xml … 共有プロパティ定義 +├─ SampleLogConf2CS.xml … log4net 設定 +├─ app.config … 接続文字列 + appSettings +└─ readme.txt … 実行方法(コマンドライン引数など) +``` + +WS 系はこれに `TMProtocolDefinition.xml` / `TMInProcessDefinition.xml` が加わる。 +Web 系は `Logic/{Business,Common,Dao}` または `AppCode/sample/{Business,Common,Dao}` に入る。 + +--- + +## 5. 呼び出しパターン + +### 5-1. インプロセス(2層C/S・バッチ・Web) + +```csharp +// P層 +TestParameterValue p = new TestParameterValue( + screenId, controlId, "SelectCount", // ← methodName が UOC_ 振り分けキー + "SQL%individual%static%-", // ← ActionType(後述) + new MyUserInfo("", "")); + +LayerB layerB = new LayerB(); +TestReturnValue r = (TestReturnValue)layerB.DoBusinessLogic(p, DbEnum.IsolationLevelEnum.ReadCommitted); + +if (r.ErrorFlag) { /* 業務例外:ErrorMessageID / ErrorMessage / ErrorInfo */ } +else { /* 正常系:r.Obj など */ } +``` + +### 5-2. サービス呼び出し(WS クライアント) + +```csharp +CallController cc = new CallController(context); +object ret = cc.Invoke("testInProcess", parameterValue); // 論理名で解決 +``` + +論理名 → プロトコル は `TMProtocolDefinition.xml`、 +論理名 → assembly/class は `TMInProcessDefinition.xml` で解決される。 + +`WSClientWPF_sample/TMProtocolDefinition.xml` の実例: + +| id | protocol | 意味 | +|---|---|---| +| `testInProcess` | 1 | インプロセス | +| `testWebService` | 2 | ASP.NET Web サービス (asmx) ※コメントアウト | +| `testWebService2` | 3 | WCF-HTTP ※コメントアウト | +| `testWebService3` | 4 | WCF-TCP (`net.tcp://localhost:7777/...`) | +| `testWebService4` | 5 | ASP.NET WebAPI (JSON-RPC) | + +`_` 始まりの id(`_testWebService` 等)は `url_ref` / `prop_ref` でマスタ データを参照する記法の例。 + +--- + +## 6. `ActionType` の規約(サンプル横断のローカル ルール) + +`%` 区切りの 4 要素。**フレームワークが解釈するのは [0] のみ**で、[1] 以降はサンプル独自。 + +| 位置 | 意味 | 値 | +|---|---|---| +| `[0]` | **データ プロバイダ選択**(フレームワークが解釈) | `SQL` `OLE` `ODB` `ODP` `MCN` `NPS` `DB2` `HIR` | +| `[1]` | Dao の種類(サンプル独自) | `common`(`CmnDao`) / `generate`(自動生成Dao) / それ以外(個別 `LayerD`) | +| `[2]` | SQL の種類(サンプル独自) | `static`(`.sql`) / `dynamic`(`.xml` = DPQ) | +| `[3]` | ロールバック試験(サンプル独自) | `Business`(業務例外) / `System`(システム例外) / `-`(正常) | + +バッチのコマンドライン例(`SimpleBatch_sample/readme.txt`): + +``` +/Dap SQL /Mode1 individual /Mode2 static /EXROLLBACK - +``` + +`StringVariableOperator.GetCommandArgs('/', out argsDic, out valsLst)` で分解し、 +**キーは大文字化されて `argsDic["/DAP"]` のように引かれる**点に注意。 + +--- + +## 7. 設定ファイル + +### 7-1. コンソール / WinForms / WPF — `app.config` + +`appSettings` に `Fx*` キー、`connectionStrings` に `ConnectionString_{SQL,OLE,ODBC,ODP,MCN}`。 +`` に **大量の `bindingRedirect`** が入っている(net48 の宿命)。 +NuGet パッケージを更新すると、ここも追随が必要。 + +### 7-2. Web — `Web.config` + `app.config` + +`WebForms_Sample` は `` で **appSettings を外部ファイルに分離**している。 +`Fx*` キーの実体は `app.config` 側にあるので、**設定を探すときは `Web.config` ではなく `app.config` を見る**。 + +P層(Web Forms)専用の設定群: + +| 種別 | キー | +|---|---| +| コントロール接頭辞 | `FxPrefixOfButton`=btn, `FxPrefixOfTextBox`=txt, `FxPrefixOfGridView`=gvw … 全 13 種 | +| 基盤画面パス | `FxErrorScreenPath` `FxOKMessageDialogPath` `FxYesNoMessageDialogPath` `FxDialogFramePath` | +| アイコン | `FxInformationIconPath` `FxWarningIconPath` `FxErrorIconPath` `FxQuestionIconPath` | +| ダイアログ既定スタイル | `FxDefaultFxDialogStyle` `FxDefaultBusinessDialogStyle` `FxDefaultNormalScreenStyle` | +| 画面制御 | `FxSessionTimeOutCheck` `FxDoubleTransmissionCheck` `FxScreenTransitionMode` `FxScreenTransitionCheck` | +| キュー長 | `FxRequestTicketGuidMaxQueueLength` `FxButtonhistoryMaxQueueLength` `FxScreeenGuidMaxQueueLength` `FxWindowGuidMaxQueueLength` | +| XML 定義 | `FxXMLSPDefinition` `FxXMLMSGDefinition` `FxXMLSCDefinition` `FxXMLTCDefinition` `FxXMLTMProtocolDefinition` `FxXMLTMInProcessDefinition` | +| `_3TierEngine` 命名規約 | `DaoClassNameHeader`=Dao, `MethodNameHeaderS`=S, `MethodNameHeaderD`=D, `MethodLabel_Ins`=1_Insert … `UpdateParamHeader`=Set_, `LikeParamFooter`=_Like | + +**`_3TierEngine` の命名規約キーは自動生成Daoのメソッド名(`S1_Insert` / `D2_Select` / `D5_SelCnt`)と直結**しており、 +片方だけ変えると実行時に解決できなくなる。 + +### 7-3. `Fx*` キーは大文字小文字を区別しない + +`MyBaseDao.SetSqlByFile2` は内部で `GetConfigValue("sqlTextFilePath")`(小文字 s)を引くが、 +`app.config` の定義は `SqlTextFilePath`(大文字 S)。 +.NET Framework の `appSettings` も `Microsoft.Extensions.Configuration` も**キー比較は大文字小文字を無視する**ため +動作するが、意図的な一致ではないので、**このキー名を「揃える」目的で書き換えない**こと。 + +--- + +## 8. ビルドと実行 + +### ビルド + +`root/programs/CS/` 直下の bat(`z_Common.bat` が MSBuild を解決)。 + +| bat | 対象 | +|---|---| +| `5_Build_2CS_sample.bat` | `2CS_sample/*` | +| `5_Build_Bat_sample.bat` | `Bat_sample/*`(4 sln を順次) | +| `5_Build_CLI_sample.bat` | `CLI_sample`(実体が無いので実質 no-op) | +| `6_Build_WSSrv_sample.bat` | `WSServer_sample` → `WS_sample/Temp` → `WS_sample/Build` へ xcopy | +| `7_Build_Framework_WS.bat` | `ServiceInterface`。`WS_sample/Build` を `WCFService/dll` へコピーしてからビルド | +| `8_Build_WSClnt_sample.bat` | `WSClient_sample/*`(4 sln) | +| `10_Build_WebApp_sample.bat` | `WebForms_Sample` → `MVC_Sample` | + +**`WS_sample/Build/` は成果物置き場**であり、`7_Build_Framework_WS.bat` が +`ServiceInterface/WCFService/dll/` へ流し込む中継点になっている(`.gitignore` 済み)。 + +Web 系は `packages.config` 方式(NuGet classic)なので、**`nuget.exe restore` が必須** +(各 bat が `..\nuget.exe restore` を実行している)。 + +### 実行 + +- バッチ: プロジェクトのプロパティ → デバッグ → コマンドライン引数に `readme.txt` の文字列を設定。 +- `AsyncEvent_sample`: sln をビルド後 `test-winx2&wpfx2.bat` から 4 プロセス起動。 +- `WebForms_Sample`: `sessionState mode="StateServer"` 既定 → **ASP.NET 状態サービスの起動が必要** + (`C:\root\files\bat\aspnet_state-stat.bat`)。 +- WS クライアント: 先に `WSServer_sample` と `ServiceInterface`(WCF/WebAPI ホスト)を起動。 + +--- + +## 9. 個別サンプルの読みどころ + +### `Bat_sample/SimpleBatch_sample` — まずここを読む + +B層(`LayerB.UOC_SelectCount` 等)が **`CmnDao` / 自動生成Dao / 個別Dao の 3 経路**を +`switch` で切り替える形になっており、Open棟梁のデータアクセス手段が 1 ファイルで俯瞰できる。 + +```csharp +switch ((testParameter.ActionType.Split('%'))[1]) +{ + case "common": CmnDao cmnDao = new CmnDao(this.GetDam()); + cmnDao.SQLFileName = "ShipperCount.sql"; // or .xml (DPQ) + testReturn.Obj = cmnDao.ExecSelectScalar(); break; + case "generate": DaoShippers genDao = new DaoShippers(this.GetDam()); + testReturn.Obj = genDao.D5_SelCnt(); break; + default: LayerD myDao = new LayerD(this.GetDam()); + myDao.SelectCount(testParameter, testReturn); break; +} +``` + +### `Dao/LayerD.cs` の `テンプレ()` メソッド + +**日本語のメソッド名「テンプレ」**が各サンプルの `LayerD` に入っており、 +`SetSqlByFile2` / `SetSqlByCommand` / `SetParameter` / `ExecXxx` の全パターンが +コメント付きで並んでいる。**D層を書くときのチートシート**として機能する。 +実運用コードにコピーする際は削除する前提。 + +### `Dao/DaoShippers.cs` — DaoGen_Tool の出力形 + +ヘッダに `作成者:棟梁 D層自動生成ツール(墨壺)` と入る。メソッド命名は +`S1_Insert` `D1_Insert` `S2_Select` `D2_Select` `S3_Update` `D3_Update` `S4_Delete` `D4_Delete` `D5_SelCnt` +(`S`=静的SQL、`D`=動的SQL(DPQ)、番号は `MethodLabel_*` 設定に対応)。 +**手で編集せず、ツールで再生成する**のが本来の運用。 + +### `WebForms_Sample` — P層機能のテストベッド + +`Aspx/` 配下の内訳: + +| ディレクトリ | .aspx 数 | 内容 | +|---|---|---| +| `testFxLayerP/` | 19 | **P層機能の網羅テスト**(最重要) | +| `testScreenCtrl/` | 6 | 画面遷移制御 | +| `sample/` | 5 | 業務サンプル | +| `start/` | 3 | ログイン・メニュー | +| `Framework/` | 3 | ダイアログ等の基盤画面 | +| `OAuth2/` | 1 | OAuth2 連携 | +| `Common/` | 1 | エラー画面 | + +`AppCode/testPublic/Business/TestMTC*.cs` はマルチ トランザクション制御の検証コード。 +`Aspx/Common/Master/testNest/` にはマスタ ページ多重ネストの検証が入っている。 + +### `Bat_sample/RerunnableBatch_sample{,2,3}` — 性能モデル 3 種 + +| | 手法 | 動的SQL | +|---|---|---| +| 無印 | 通常のデータアクセス(`S1_Insert` / `D1_Insert` を切替) | 可 | +| `2` | `SQLUtility` + `ExecGenerateSQL` でラウンドトリップ削減 | 可 | +| `3` | `SQLUtility` で DataTable から Insert 文を生成 | **不可(静的のみ)** | + +--- + +## 10. 落とし穴 + +1. **`4_Build_CopyAssemblies.bat` を飛ばすと全サンプルがビルドできない。** + `Build\`(`Build_net48` のコピー)を `HintPath` 参照しているため。 +2. **`C:\root\files\...` の絶対パス依存。** チェックアウト先が `C:\root` 以外だと実行時に落ちる。 + IDE から F5 する前に `C:\root\files` の存在を確認すること。 +3. **`net48` のみ。** .NET (Core) 版は `../Samples4NetCore/Legacy/` にある**別コピー**。 + B層・D層のソースは**ほぼ同一だが独立管理**(4-2 参照)→ **片方を直したらもう片方も直す**。 +4. **`ReturnValue` を設定し忘れると戻り値が null。** `UOC_` メソッドの冒頭で必ず + `this.ReturnValue = testReturn;` する(フレームワーク側の仕様。`../Frameworks/ANALYSIS.md` 3.2 節)。 +5. **`app.config` の `bindingRedirect` が大量**。NuGet 更新時は追随が必要。 +6. **`WebForms_Sample` / `MVC_Sample` は `packages.config` 方式**。`PackageReference` 移行はされていない。 + `nuget.exe restore` を忘れるとビルドが落ちる。 +7. **`CLI_sample` にコードは無い**(README のみ)。実装を探すなら `../Samples4NetCore/Legacy/CLI_sample/`。 +8. **`WS_sample/Build/` `WS_sample/Temp/` はビルド生成物**。コミット対象ではない(`Build/` は `.gitignore` 済み)。 +9. **`_3TierEngine` の命名規約キーと自動生成Daoのメソッド名は連動**。片方だけ変えない(7-2 参照)。 +10. **VB 版ミラーが存在**(`root/programs/VB/Samples/`)。構成はほぼ 1:1 対応。 + +--- + +## 11. `Samples` と `Samples4NetCore/Legacy` の関係 + +`Samples4NetCore/Legacy/` は `Samples/` を **.NET (Core) 向けに移植した独立コピー**。 +`Compile Include` によるファイル共有は**していない**(リンク参照ゼロ)。 + +実測した差分: + +| サンプル群 | 同一ファイル | 差異あり | `Samples` 側のみ | +|---|---|---|---| +| `2CS_sample` | 138 | 18 | 26 | +| `Bat_sample` | 73 | 14 | 8 | +| `WS_sample` | 65 | 14 | 36 | + +- **`Business/LayerB.cs` や `Dao/*.cs` は多くがバイト単位で同一。** +- 差異があるのは主に `*.csproj` / `*.sln` / `Program.cs`(Core 側は `GetConfigParameter.InitConfiguration()` 呼び出しが増える)。 +- `Samples` 側のみ = `app.config`(Core は `appsettings.json`)、`Properties/AssemblyInfo.cs`(SDK 形式では自動生成)、 + および未移植の `AsyncEvent_sample` / `WSClientWinCone_sample`。 + +→ **B層・D層のロジックを修正したら、`Samples4NetCore/Legacy/` 側の同名ファイルも同じ修正が必要。** + +--- + +## 12. エージェント向け作業チェックリスト + +- [ ] `AGENTS.md` のポリシー遵守(**git 操作をしない**) +- [ ] 変更が `Samples4NetCore/Legacy/` 側にも必要か判定(11 節) +- [ ] `Frameworks` を先にビルド → `4_Build_CopyAssemblies.bat` を実行(`Build\` を作る) +- [ ] Web 系を触るなら `nuget.exe restore`(`packages.config` 方式) +- [ ] 新規 .cs にはヘッダ コメント(Apache License / クラス名・日本語名・更新履歴)を付与、既存変更時は履歴に 1 行追記。 + **Copyright ブロックは新規には付けない**(`../Frameworks/ANALYSIS.md` 8.1 節) +- [ ] `UOC_` メソッドの冒頭で `this.ReturnValue = ...` を設定 +- [ ] `ActionType` の `%` 区切り規約を壊さない(6 節) +- [ ] 設定キーを増やしたら `app.config`(Web は `app.config` 側)に追記 +- [ ] 実行確認をするなら `C:\root\files` と Northwind DB の準備状況を先に確認 diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/MVC_Sample.csproj b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/MVC_Sample.csproj index 60da843d2..a69202e32 100644 --- a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/MVC_Sample.csproj +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/MVC_Sample.csproj @@ -318,6 +318,8 @@ + + diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js new file mode 100644 index 000000000..85a9b1dad --- /dev/null +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js @@ -0,0 +1,205 @@ +// Unobtrusive Ajax support library for jQuery +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// @version v3.2.6 +// +// Microsoft grants you the right to use these script files for the sole +// purpose of either: (i) interacting through your browser with the Microsoft +// website or online service, subject to the applicable licensing or use +// terms; or (ii) using the files as included with a Microsoft product subject +// to that product's license terms. Microsoft reserves all other rights to the +// files not expressly granted by Microsoft, whether by implication, estoppel +// or otherwise. Insofar as a script file is dual licensed under GPL, +// Microsoft neither took the code under GPL nor distributes it thereunder but +// under the terms set out in this paragraph. All notices and licenses +// below are for informational purposes only. + +/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ +/*global window: false, jQuery: false */ + +(function ($) { + var data_click = "unobtrusiveAjaxClick", + data_target = "unobtrusiveAjaxClickTarget", + data_validation = "unobtrusiveValidation"; + + function getFunction(code, argNames) { + var fn = window, parts = (code || "").split("."); + while (fn && parts.length) { + fn = fn[parts.shift()]; + } + if (typeof (fn) === "function") { + return fn; + } + argNames.push(code); + return Function.constructor.apply(null, argNames); + } + + function isMethodProxySafe(method) { + return method === "GET" || method === "POST"; + } + + function asyncOnBeforeSend(xhr, method) { + if (!isMethodProxySafe(method)) { + xhr.setRequestHeader("X-HTTP-Method-Override", method); + } + } + + function asyncOnSuccess(element, data, contentType) { + var mode; + + if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us + return; + } + + mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); + $(element.getAttribute("data-ajax-update")).each(function (i, update) { + var top; + + switch (mode) { + case "BEFORE": + $(update).prepend(data); + break; + case "AFTER": + $(update).append(data); + break; + case "REPLACE-WITH": + $(update).replaceWith(data); + break; + default: + $(update).html(data); + break; + } + }); + } + + function asyncRequest(element, options) { + var confirm, loading, method, duration; + + confirm = element.getAttribute("data-ajax-confirm"); + if (confirm && !window.confirm(confirm)) { + return; + } + + loading = $(element.getAttribute("data-ajax-loading")); + duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0; + + $.extend(options, { + type: element.getAttribute("data-ajax-method") || undefined, + url: element.getAttribute("data-ajax-url") || undefined, + cache: (element.getAttribute("data-ajax-cache") || "").toLowerCase() === "true", + beforeSend: function (xhr) { + var result; + asyncOnBeforeSend(xhr, method); + result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); + if (result !== false) { + loading.show(duration); + } + return result; + }, + complete: function () { + loading.hide(duration); + getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); + }, + success: function (data, status, xhr) { + asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); + getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); + }, + error: function () { + getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments); + } + }); + + options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); + + method = options.type.toUpperCase(); + if (!isMethodProxySafe(method)) { + options.type = "POST"; + options.data.push({ name: "X-HTTP-Method-Override", value: method }); + } + + // change here: + // Check for a Form POST with enctype=multipart/form-data + // add the input file that were not previously included in the serializeArray() + // set processData and contentType to false + var $element = $(element); + if ($element.is("form") && $element.attr("enctype") == "multipart/form-data") { + var formdata = new FormData(); + $.each(options.data, function (i, v) { + formdata.append(v.name, v.value); + }); + $("input[type=file]", $element).each(function () { + var file = this; + $.each(file.files, function (n, v) { + formdata.append(file.name, v); + }); + }); + $.extend(options, { + processData: false, + contentType: false, + data: formdata + }); + } + // end change + + $.ajax(options); + } + + function validate(form) { + var validationInfo = $(form).data(data_validation); + return !validationInfo || !validationInfo.validate || validationInfo.validate(); + } + + $(document).on("click", "a[data-ajax=true]", function (evt) { + evt.preventDefault(); + asyncRequest(this, { + url: this.href, + type: "GET", + data: [] + }); + }); + + $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { + var name = evt.target.name, + target = $(evt.target), + form = $(target.parents("form")[0]), + offset = target.offset(); + + form.data(data_click, [ + { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, + { name: name + ".y", value: Math.round(evt.pageY - offset.top) } + ]); + + setTimeout(function () { + form.removeData(data_click); + }, 0); + }); + + $(document).on("click", "form[data-ajax=true] :submit", function (evt) { + var name = evt.currentTarget.name, + target = $(evt.target), + form = $(target.parents("form")[0]); + + form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []); + form.data(data_target, target); + + setTimeout(function () { + form.removeData(data_click); + form.removeData(data_target); + }, 0); + }); + + $(document).on("submit", "form[data-ajax=true]", function (evt) { + var clickInfo = $(this).data(data_click) || [], + clickTarget = $(this).data(data_target), + isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); + evt.preventDefault(); + if (!isCancel && !validate(this)) { + return; + } + asyncRequest(this, { + url: this.action, + type: this.method || "GET", + data: clickInfo.concat($(this).serializeArray()) + }); + }); +}(jQuery)); diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js new file mode 100644 index 000000000..ae780ac8a --- /dev/null +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js @@ -0,0 +1,16 @@ +// Unobtrusive Ajax support library for jQuery +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// @version v3.2.6 +// +// Microsoft grants you the right to use these script files for the sole +// purpose of either: (i) interacting through your browser with the Microsoft +// website or online service, subject to the applicable licensing or use +// terms; or (ii) using the files as included with a Microsoft product subject +// to that product's license terms. Microsoft reserves all other rights to the +// files not expressly granted by Microsoft, whether by implication, estoppel +// or otherwise. Insofar as a script file is dual licensed under GPL, +// Microsoft neither took the code under GPL nor distributes it thereunder but +// under the terms set out in this paragraph. All notices and licenses +// below are for informational purposes only. +!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery); \ No newline at end of file diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml index 781f02a0c..91b3a57ea 100644 --- a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml +++ b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml @@ -69,10 +69,10 @@ @if (User.Identity.IsAuthenticated) { @* 各メニューは、ユーザーが認証されている時だけ表示する *@ -
  • +
  • メニュー1
  • -
  • +
  • メニュー2
  • } diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/loading.gif b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/loading.gif new file mode 100644 index 000000000..3e0220309 Binary files /dev/null and b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/loading.gif differ diff --git a/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/logo.png b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/logo.png new file mode 100644 index 000000000..a28bca100 Binary files /dev/null and b/root/programs/CS/Samples/WebApp_sample/MVC_Sample/MVC_Sample/images/touryo/logo.png differ diff --git a/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js b/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js index d9584cf27..c0f54afbc 100644 --- a/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js +++ b/root/programs/CS/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js @@ -44,6 +44,9 @@ //* 2019/03/04 西野 大介 二重送信防止のブラウザ判定処理を修正 //* 2019/03/04 西野 大介 WebForms版とMVC版のDiffを取り易く修正。 //* 2020/03/19 西野 大介 モダン・ブラウザ・サポート(2017/04/20)の制限事項解除 +//* 2026/08/01 玄人 幸道 業務モーダル画面を閉じた際に親画面がPost Backされない問題に対応 +//* (unloadイベントがブラウザ側で無効化されたため、 +//*  window.closedのポーリングによる終了検知を併用する) //********************************************************************************** // --------------------------------------------------------------- @@ -938,11 +941,24 @@ function Fx_CallbackOfBusinessModalScreen() { // --------------------------------------------------------------- function Fx_CallbackOfBusinessModalScreen2() { + // ↓↓↓【追加】↓↓↓ + // unloadイベントとポーリングの両方から呼ばれる可能性があるため、二重実行を防ぐ。 + if (Fx_BusinessPseudoModelDialog === null + || Fx_BusinessPseudoModelDialog === undefined) { + return; + } + // ↑↑↑【追加】↑↑↑ + // イベントを外す if (Fx_BusinessPseudoModelDialog.closed) { // 閉じている。 $(Fx_BusinessPseudoModelDialog).off("unload"); //, Fx_CallbackOfBusinessModalScreen); Fx_BusinessPseudoModelDialog = null; + + // ↓↓↓【追加】↓↓↓ + // 終了検知のポーリングも解除する。 + Fx_ClearWatcherOfBusinessModalScreen(); + // ↑↑↑【追加】↑↑↑ } else { // 閉じていない。 // unloadのCallbackを"再度"仕掛ける。 @@ -1129,8 +1145,61 @@ function Fx_SetCallbackOfBusinessModalScreen() { // --------------------------------------------------------------- function Fx_SetCallbackOfBusinessModalScreen2() { $(Fx_BusinessPseudoModelDialog).on("unload", Fx_CallbackOfBusinessModalScreen); + + // ↓↓↓【追加】↓↓↓ + // unloadイベントは、モダン・ブラウザ側で無効化が進んでおり発火しないことがある + // (Chromeでは document.featurePolicy.allowsFeature("unload") が false になる)。 + // このため、window.closed のポーリングでも子画面の終了を検知する。 + Fx_SetWatcherOfBusinessModalScreen(); + // ↑↑↑【追加】↑↑↑ } +// ↓↓↓【追加】↓↓↓ + +// Business疑似Model(実体はModeless)Screenの終了監視タイマ +var Fx_WatcherOfBusinessPseudoModelDialog = null; + +// --------------------------------------------------------------- +// モダンブラウザ版(window.closedのポーリングによる終了検知を仕掛ける) +// --------------------------------------------------------------- +// 引数 - +// 戻り値 - +// --------------------------------------------------------------- +function Fx_SetWatcherOfBusinessModalScreen() { + + // 多重に仕掛けない。 + Fx_ClearWatcherOfBusinessModalScreen(); + + Fx_WatcherOfBusinessPseudoModelDialog = setInterval( + function () { + if (Fx_BusinessPseudoModelDialog === null + || Fx_BusinessPseudoModelDialog === undefined + || Fx_BusinessPseudoModelDialog.closed) { + + // 閉じられたので、監視を終了して後処理を実行する。 + Fx_ClearWatcherOfBusinessModalScreen(); + Fx_CallbackOfBusinessModalScreen(); + } + }, + TimeLag4BusinessPseudoModelDialog); +} + +// --------------------------------------------------------------- +// モダンブラウザ版(終了検知のポーリングを解除する) +// --------------------------------------------------------------- +// 引数 - +// 戻り値 - +// --------------------------------------------------------------- +function Fx_ClearWatcherOfBusinessModalScreen() { + + if (Fx_WatcherOfBusinessPseudoModelDialog !== null) { + clearInterval(Fx_WatcherOfBusinessPseudoModelDialog); + Fx_WatcherOfBusinessPseudoModelDialog = null; + } +} + +// ↑↑↑【追加】↑↑↑ + //********************************************************************************** // フレームワーク機能(Ajax Extension) //********************************************************************************** diff --git a/root/programs/CS/Samples4NetCore/ANALYSIS.md b/root/programs/CS/Samples4NetCore/ANALYSIS.md new file mode 100644 index 000000000..a50dac59a --- /dev/null +++ b/root/programs/CS/Samples4NetCore/ANALYSIS.md @@ -0,0 +1,360 @@ +# ANALYSIS.md — Open棟梁 サンプル アプリ(CS/Samples4NetCore)コード分析 + +対象: `root/programs/CS/Samples4NetCore`(**.NET 10.0**) / ブランチ: `develop` +最終更新: 2026-07-31 + +本書は **コーディング・エージェントが本ディレクトリで作業する際の Context** を目的とする。 +フレームワーク本体は `../Frameworks/ANALYSIS.md`、net48 版サンプルは `../Samples/ANALYSIS.md` を参照。 + +--- + +## 1. これは何か + +Open棟梁の **.NET (Core) 系サンプル**。3 つの区画に分かれており、性格がまったく違う。 + +| 区画 | 中身 | 性格 | +|---|---|---| +| **`Backend/`** | `MVC_Sample`(ASP.NET Core MVC) | **現行の推奨サンプル。** ここが本命 | +| **`Frontend/`** | README のみ | 別リポジトリ `FrontendTemplates` へ移動済み | +| **`Legacy/`** | `2CS_sample` / `Bat_sample` / `CLI_sample` / `WS_sample` | `../Samples`(net48)を .NET へ移植した**独立コピー**。名前どおり「レガシー」扱い | + +**全プロジェクトが SDK 形式 csproj / `net10.0`(GUI は `net10.0-windows7.0`)。** + +--- + +## 2. 前提条件 + +### 2-1. フレームワークを先にビルドする(最重要) + +**18 プロジェクト中 17 が `Build_netcore100\net10.0\*.dll` を `HintPath` で直接参照する** +(例外は `Legacy/CLI_sample/Simple_CLI` のみ。こちらはフレームワーク非依存)。 +`ProjectReference` ではないので、**フレームワークをビルドしない限り古い / 存在しない DLL を見る。** + +```xml + + ..\..\..\..\Frameworks\Infrastructure\Build_netcore100\net10.0\OpenTouryo.Framework.dll + +``` + +``` +dotnet build ../Frameworks/Infrastructure/Nuget_netcore100.sln ★先にこれ +dotnet build ../Frameworks/Infrastructure/Business_netcore100.sln +→ その後に各サンプル +``` + +> net48 側の `Samples` が参照する `Build\` とは**別のディレクトリ**。 +> `4_Build_CopyAssemblies.bat`(`Build_net48` → `Build\`)は **.NET (Core) 側には関係しない**。 + +### 2-2. リポジトリを `C:\root\` に配置する + +`Backend/MVC_Sample` と `Legacy/*` の設定は `C:/root/files/resource/...` を直書きしている。 + +```json +"FxXMLSPDefinition": "C:/root/files/resource/XML/SPDefinition.xml", +"SqlTextFilePath": "C:/root/files/resource/Sql" +``` + +チェックアウト先が `C:\root` 以外(例: `C:\OpenTouryo\root`)の場合、**ビルドは通るが実行時に落ちる**。 +net48 側と違い **区切り文字が `/`**(JSON なのでエスケープ回避)。 + +### 2-3. データベース + +SQL Server の **Northwind** が既定。`Legacy/Bat_sample/RerunnableBatch_sample*` は `ORDERS2` テーブルが追加で必要。 +接続文字列は net48 版と同一のサンプル値(`localhost` / `sa` / `seigi@123` 等)。 +Core 側は **PostgreSQL (`ConnectionString_NPS`) が追加**されている点が net48 版との差。 + +--- + +## 3. `Backend/MVC_Sample` — 現行の推奨サンプル + +ASP.NET Core MVC(`Microsoft.NET.Sdk.Web` / `net10.0`)。`Startup.cs` 方式(Minimal API ではない)。 + +### 3-1. フレームワークの組み込み方(テンプレートとして重要) + +```csharp +// Program.cs +public static void Main(string[] args) +{ + OAuth2AndOIDCClient.HttpClient = new HttpClient(); // ★静的 HttpClient を差し込む + Program.BuildWebHost(args).Run(); +} + +// Startup.cs +public Startup(IConfiguration configuration) +{ + Configuration = configuration; + GetConfigParameter.InitConfiguration(configuration); // ★必須。これが無いと Fx* 設定が全て null +} + +public void Configure(IApplicationBuilder app, IWebHostEnvironment env) +{ + app._UseHttpContextAccessor(); // ★必須。MyHttpContext.Current を有効化する拡張メソッド + ... + app.UseSession(new SessionOptions() { ... }); // セッション機能を使うなら必須 +} +``` + +**この 3 点(`InitConfiguration` / `_UseHttpContextAccessor` / `UseSession`)が +.NET (Core) で Open棟梁 を動かすための定型**。`_UseHttpContextAccessor` は +`Touryo.Infrastructure.Framework.StdMigration.HttpContextExtensions` の拡張メソッドで、 +`System.Web.HttpContext.Current` 相当を `MyHttpContext.Current` として復活させる。 + +### 3-2. 構成 + +``` +MVC_Sample/ +├─ Program.cs / Startup.cs +├─ Controllers/ +│ ├─ Crud1Controller.cs … Ajax(部分更新)版 CRUD +│ ├─ Crud2Controller.cs … Html.BeginForm(全体更新)版 CRUD +│ ├─ HomeController.cs … ログイン / OAuth2 認可コードグラント / ログアウト +│ ├─ ErrorController.cs +│ └─ PingController.cs … 死活監視(MyBaseMVControllerCore を継承しない素の Controller) +├─ Logic/Business/LayerB.cs … B層 +├─ Logic/Common/Test*Value.cs … 引数・戻り値クラス +├─ Logic/Dao/{LayerD,DaoShippers}.cs … D層 +├─ Models/ViewModels/*.cs +├─ Views/{Crud1,Crud2,Home,Error,Shared}/*.cshtml +├─ wwwroot/{css,js,images}/ … bootstrap 等はリポジトリに直接格納(npm 不使用) +├─ appsettings.json / appsettings.Development.json +└─ Properties/launchSettings.json +``` + +- コントローラは **`MyBaseMVControllerCore` を継承**(`Touryo.Infrastructure.Business.Presentation`)。 +- **`[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]`** が + `Crud1` / `Crud2` に付与されており、Cookie 認証必須。 +- B層呼び出しは **`await layerB.DoBusinessLogicAsync(...)`**(net48 版は同期の `DoBusinessLogic`)。 + +```csharp +public async Task SelectCount(CrudViweModel model) +{ + LayerB layerB = new LayerB(); + TestReturnValue r = (TestReturnValue)await layerB.DoBusinessLogicAsync( + testParameterValue, this.SelectIsolationLevel(model.DdlIso)); + ... +} +``` + +- `Crud1` = Ajax 部分更新(`_ChartView.cshtml` / `_MessageView.cshtml` を部分レンダリング) +- `Crud2` = `Html.BeginForm` で全体更新 + → **同じ業務ロジックを 2 つの UI 方式で呼ぶ対比サンプル**になっている。 + +### 3-3. 認証(`HomeController`) + +- フォーム ログイン: `ClaimsIdentity` / `ClaimsPrincipal` を組み立てて `SignInAsync` +- **OAuth2 認可コードグラント**: `OAuth2AndOIDCClient.GetAccessTokenByCodeAsync` → + id_token 検証 → `GetUserInfoAsync` → `SignInAsync` +- 接続先は `appsettings.json` の `SpRp_*` / `OAuth2AndOidc*` / `JwkSetUri` + (既定は `https://localhost:44300/MultiPurposeAuthSite/...` = 別リポジトリの汎用認証サイト) + +**この OAuth2 フローを動かすには MultiPurposeAuthSite が別途必要。** 単体では Login 画面までしか動かない。 + +### 3-4. npm / grunt は使わない + +**`wwwroot/lib/` 配下(bootstrap 等)はリポジトリに直接格納**されており、 +`package.json` / `gruntfile.js` / `RestoreLib1.bat` / `RestoreLib2.bat` は存在しない +(コミット `2a08482f` で npm/grunt を廃止した)。`10_Build_WebAppCore_sample.bat` も npm 手順を持たない。 + +### 3-5. 起動 + +``` +dotnet run --project Backend/MVC_Sample/MVC_Sample/MVC_Sample.csproj +``` + +`launchSettings.json` のプロファイル: `http`(5219) / `https`(7014) / `IIS Express`(26422, ssl 44383)。 + +--- + +## 4. `Legacy/` — net48 版からの移植 + +`../Samples/` の **独立コピー**。`Compile Include` によるファイル共有は**していない**。 + +| ディレクトリ | 中身 | net48 版との差 | +|---|---|---| +| `Legacy/2CS_sample` | 2CSClientWin / 2CSClientWPF / CustCtrl / GenDaoAndBatUpd / TimeStamp | **`AsyncEvent_sample` が未移植** | +| `Legacy/Bat_sample` | SimpleBatch / RerunnableBatch ×3 | 同等 | +| `Legacy/CLI_sample` | Simple_CLI / DAG_Login_CLI / LIR_Login_CLI | **こちらにしか実体が無い**(後述) | +| `Legacy/WS_sample` | WSServer / WSIFType / WSClient ×3 | **`WSClientWinCone_sample` が未移植** | + +### 4-1. `Samples`(net48)との同一性 — 実測 + +| サンプル群 | 同一ファイル | 差異あり | net48 側のみ | +|---|---|---|---| +| `2CS_sample` | 138 | 18 | 26 | +| `Bat_sample` | 73 | 14 | 8 | +| `WS_sample` | 65 | 14 | 36 | + +- **`Business/LayerB.cs` や `Dao/*.cs` は多くがバイト単位で同一。** +- 差異があるのは主に `*.csproj` / `*.sln` / `Program.cs`。 +- net48 側のみ = `app.config`(Core は `appsettings.json`)、`Properties/AssemblyInfo.cs`(SDK 形式は自動生成)。 + +→ **B層・D層のロジックを直したら `../Samples/` 側の同名ファイルも同じ修正が必要。** + +### 4-2. `Program.cs` の差分(移植の定型) + +Core 側は **冒頭で config を明示初期化する**のが唯一の実質的な差。 + +```csharp +// configの初期化(net48 版には無い) +string dir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory + .FullName.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); +GetConfigParameter.InitConfiguration(dir + "/appsettings.json"); +``` + +以降の `TestParameterValue` 生成 → `layerB.DoBusinessLogic(...)` は net48 版と同一。 + +### 4-3. `Legacy/CLI_sample` — ここにしか無い + +net48 版は README のみ(Sharprompt が .NET Framework サポートを終了したため)。 +実体は Core 側だけに存在する。 + +| プロジェクト | 内容 | +|---|---| +| `Simple_CLI` | `System.CommandLine` + `Sharprompt` の CLI テンプレート。**フレームワーク非依存**(`OpenTouryo.*` 参照なし) | +| `DAG_Login_CLI` | OAuth 2.0 **Device Authorization Grant** クライアント | +| `LIR_Login_CLI` | OAuth 2.0 for Native Apps の **Loopback Interface Redirection** | + +`DAG` / `LIR` は `OpenTouryo.Framework` / `Public` / `Public.Security` を参照する。 + +> **注意**: `System.CommandLine` が **`2.0.0-beta1.21216.1`(2021 年の beta)** で固定されている。 +> net48 版 README には「beta が解除され Ctrl-C で CancellationToken がハングする問題が修正されたら移植する」 +> と書かれており、この beta 依存は**意図的に据え置かれている**。安易に上げない。 + +### 4-4. `Legacy/WS_sample` — リモート プロトコルは実質使えない + +`TMProtocolDefinition.xml` は net48 版からコピーされており `protocol="2"〜"5"`(asmx / WCF-HTTP / +WCF-TCP / WebAPI)の定義が残っているが、**.NET (Core) の `FxEnum.TmProtocol` は `InProcess`(1) しか持たない** +(`../Frameworks/ANALYSIS.md` 6.4 節)。 + +さらに `7_Build_Framework_WSCore.bat` はサービス ホスト側のビルドを丸ごと `rem` で無効化しており、 +理由が `Core系のBinarySerializeの完全廃止対応` と記されている。 + +→ **Core 側の WS_sample は `testInProcess`(インプロセス呼び出し)でのみ動作する。** +定義ファイルに remote の記述が残っていることに惑わされないこと。 + +--- + +## 5. 設定(`appsettings.json`) + +net48 の `app.config` → Core は `appsettings.json`。**`appSettings` / `connectionStrings` という +セクション名を JSON でもそのまま使う**のが Open棟梁の流儀。 + +```json +{ + "connectionStrings": { + "ConnectionString_SQL": "Data Source=localhost;Initial Catalog=Northwind;...", + "ConnectionString_NPS": "HOST=localhost;DATABASE=postgres;..." + }, + "appSettings": { + "FxXMLSPDefinition": "C:/root/files/resource/XML/SPDefinition.xml", + "FxLog4NetConfFile": "C:/root/files/resource/Log/SampleLogConf.xml", + "FxSqlTraceLog": "on", + "SqlTextFilePath": "C:/root/files/resource/Sql" + } +} +``` + +- **`appsettings.json` はコメント付き JSON(JSONC)**で書かれている。 + `Microsoft.Extensions.Configuration.Json` は `//` コメントを許容するが、 + 厳密な JSON パーサで読むと壊れるので注意。 +- `Legacy/*` は `csproj` で `Always` を + `appsettings.json` / `MSGDefinition.xml` / `SPDefinition.xml` / `SampleLogConf2CS.xml` に指定している。 + **定義ファイルを追加したら csproj にもコピー指定を足す**必要がある。 +- `Backend/MVC_Sample` は Web SDK なので `appsettings.json` は自動でコピーされる。 + +--- + +## 6. ビルド + +`root/programs/CS/` 直下の bat(内部は `dotnet restore` + `dotnet msbuild`)。 + +| bat | 対象 | +|---|---| +| `5_Build_2CSCore_sample.bat` | `Legacy/2CS_sample/*` | +| `5_Build_BatCore_sample.bat` | `Legacy/Bat_sample/*`(4 sln) | +| `5_Build_CLICore_sample.bat` | `Legacy/CLI_sample/*` | +| `6_Build_WSSrvCore_sample.bat` | `Legacy/WS_sample/WSServer_sample` → `Temp` → `Build/net10.0` へ xcopy | +| `7_Build_Framework_WSCore.bat` | **中身が `rem` で無効化されている**(no-op) | +| `8_Build_WSClntCore_sample.bat` | `Legacy/WS_sample/WSClient_sample/*` | +| `10_Build_WebAppCore_sample.bat` | `Backend/MVC_Sample` | + +bat を経由せず **`dotnet build ` を直接叩いてよい**(Core 側は MSBuild.exe 不要)。 +ただし **フレームワークを先にビルドする**こと(2-1 節)。 + +--- + +## 7. 依存パッケージのバージョン ドリフト(実測) + +サンプルはフレームワークを `HintPath` で直接参照するため **NuGet の推移的解決が効かない**。 +.NET には binding redirect も無いので、**サンプル側のパッケージ版がフレームワーク側より古いと +起動直後に `FileNotFoundException`(`Could not load file or assembly ...`)で落ちる。** + +`log4net` は全プロジェクトで **3.3.0**(フレームワーク本体と一致)に統一済み。 + +一方、以下は依然としてプロジェクトごとに版が違う。 + +| パッケージ | 混在しているバージョン | +|---|---| +| `Microsoft.Data.SqlClient` | **6.0.2**(Legacy) / **6.1.3**(Backend/MVC_Sample) / 6.0.1(フレームワーク) | +| `Newtonsoft.Json` | **13.0.3**(Legacy/フレームワーク) / **13.0.4**(Backend/MVC_Sample) | +| `Microsoft.Extensions.Configuration*` | 9.0.5 / 9.0.6 / 9.0.4(フレームワーク) | +| `System.Data.Odbc` | 9.0.5 / 9.0.6 | + +サンプル側が**新しい**分には動作するが、**フレームワーク側が上がったとき(Dependabot 等)に +サンプルが取り残されると即座に起動不能になる**。フレームワークの依存を上げたら、 +サンプル側(`Backend` / `Legacy` の全 csproj)も同時に上げること。 + +--- + +## 8. 落とし穴 + +1. **フレームワークを先にビルドしないと `HintPath` 参照が解決できない。** これが最頻の失敗要因。 +2. **`GetConfigParameter.InitConfiguration(...)` を呼ばないと `Fx*` 設定が全て null** + になり、定義ファイルが読めず例外になる。net48 には無かった手順。 +3. **`app._UseHttpContextAccessor()` を呼ばないと `MyHttpContext.Current` が null。** + Web アプリで必須。 +4. **`C:/root/files/...` の絶対パス依存。** ビルドは通るが実行時に落ちる。 +5. **`Legacy/` は `../Samples/` の独立コピー。** 片方を直したらもう片方も直す(4-1 節)。 +6. **Core では `CallController` のリモート プロトコルが使えない**(`InProcess` のみ)。 + `TMProtocolDefinition.xml` に残る `protocol="2"〜"5"` は死んだ定義(4-4 節)。 +7. **`_3TierEngine` / `MyBaseLogic` は .NET (Core) 版フレームワークに含まれない** + (`Business_netcore100.csproj` が `Compile Remove` している)。 + Core のサンプルが使うのは `MyFcBaseLogic` 系のみ。 +8. **`System.CommandLine` の beta 固定は意図的**(4-3 節)。 +9. **`appsettings.json` はコメント付き JSON。** +10. **`Legacy/WS_sample/Build/` `Temp/` はビルド生成物**(`Build/` は `.gitignore` 済み)。 +11. **`ReturnValue` を設定し忘れると戻り値が null**(フレームワーク仕様。`../Frameworks/ANALYSIS.md` 3.2 節)。 +12. **`Frontend/` に実体は無い。** `OpenTouryoProject/FrontendTemplates` を見ること。 +13. **`Backend/ASPNETWebService/` にも実体は無い。** `OpenTouryoProject/ResourceServerTemplates` へ移動済み。 + +--- + +## 9. `Samples`(net48)との対応表 + +| | `../Samples`(net48) | `Samples4NetCore` | +|---|---|---| +| TFM | `net48`(旧形式 csproj) | `net10.0` / `net10.0-windows7.0`(SDK 形式) | +| フレームワーク参照 | `Build\`(`4_Build_CopyAssemblies.bat` が生成) | `Build_netcore100\net10.0\` を直接 | +| 設定 | `app.config`(+ Web は `Web.config`) | `appsettings.json` | +| config 初期化 | 不要(暗黙) | **`InitConfiguration()` が必須** | +| Web | Web Forms(38 画面)+ MVC5 | ASP.NET Core MVC のみ | +| B層呼び出し | 同期 `DoBusinessLogic` | 非同期 `DoBusinessLogicAsync`(Backend) | +| WS リモート | asmx / WCF-HTTP / WCF-TCP / WebAPI | **InProcess のみ** | +| CLI | README のみ | **実体あり** | +| 非同期イベント | `AsyncEvent_sample` あり | 未移植 | +| NuGet | `packages.config`(Web) | `PackageReference` | + +--- + +## 10. エージェント向け作業チェックリスト + +- [ ] `AGENTS.md` のポリシー遵守(**git 操作をしない**) +- [ ] **フレームワークを先にビルド**(`Nuget_netcore100.sln` → `Business_netcore100.sln`) +- [ ] `Legacy/` を触ったら `../Samples/` 側の同名ファイルの追随要否を判定・報告(4-1 節) +- [ ] Web アプリを新規に起こすなら `InitConfiguration` / `_UseHttpContextAccessor` / `UseSession` を忘れない +- [ ] 定義 XML を追加したら `Legacy/*` の csproj に `CopyToOutputDirectory` を追記 +- [ ] パッケージ バージョンを変えるならフレームワーク本体との整合を確認(7 節) +- [ ] 新規 .cs にはヘッダ コメント(Apache License / クラス名・日本語名・更新履歴)を付与、既存変更時は履歴に 1 行追記。 + **Copyright ブロックは新規には付けない**(`../Frameworks/ANALYSIS.md` 8.1 節) +- [ ] `UOC_` メソッドの冒頭で `this.ReturnValue = ...` を設定 +- [ ] 実行確認をするなら `C:\root\files` と Northwind DB の準備状況を先に確認 diff --git a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/MVC_Sample.csproj b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/MVC_Sample.csproj index 93a6ce2a8..fe2f7d83d 100644 --- a/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/MVC_Sample.csproj +++ b/root/programs/CS/Samples4NetCore/Backend/MVC_Sample/MVC_Sample/MVC_Sample.csproj @@ -11,7 +11,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWPF_sample/2CSClientWPF_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWPF_sample/2CSClientWPF_sample.csproj index 5b07b1de6..ea085d287 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWPF_sample/2CSClientWPF_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWPF_sample/2CSClientWPF_sample.csproj @@ -23,7 +23,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWin_sample/2CSClientWin_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWin_sample/2CSClientWin_sample.csproj index d8337f210..3a06822d3 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWin_sample/2CSClientWin_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/2CSClientWin_sample/2CSClientWin_sample.csproj @@ -25,7 +25,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/GenDaoAndBatUpd_sample/GenDaoAndBatUpd_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/GenDaoAndBatUpd_sample/GenDaoAndBatUpd_sample.csproj index f964bfc59..56353541b 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/GenDaoAndBatUpd_sample/GenDaoAndBatUpd_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/GenDaoAndBatUpd_sample/GenDaoAndBatUpd_sample.csproj @@ -136,7 +136,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/TimeStamp_sample/TimeStamp_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/TimeStamp_sample/TimeStamp_sample.csproj index 8043b9b0b..b42243277 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/TimeStamp_sample/TimeStamp_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/2CS_sample/TimeStamp_sample/TimeStamp_sample.csproj @@ -239,7 +239,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample/RerunnableBatch_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample/RerunnableBatch_sample.csproj index 9de4b1dc1..ea6eee18b 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample/RerunnableBatch_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample/RerunnableBatch_sample.csproj @@ -16,7 +16,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample2/RerunnableBatch_sample2.csproj b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample2/RerunnableBatch_sample2.csproj index 9de4b1dc1..ea6eee18b 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample2/RerunnableBatch_sample2.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample2/RerunnableBatch_sample2.csproj @@ -16,7 +16,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample3/RerunnableBatch_sample3.csproj b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample3/RerunnableBatch_sample3.csproj index 9de4b1dc1..ea6eee18b 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample3/RerunnableBatch_sample3.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/RerunnableBatch_sample3/RerunnableBatch_sample3.csproj @@ -16,7 +16,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/SimpleBatch_sample/SimpleBatch_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/SimpleBatch_sample/SimpleBatch_sample.csproj index 4bf9b12e9..942929f1d 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/SimpleBatch_sample/SimpleBatch_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/Bat_sample/SimpleBatch_sample/SimpleBatch_sample.csproj @@ -15,7 +15,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWPF_sample/WSClientWPF_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWPF_sample/WSClientWPF_sample.csproj index 3f12d6375..c0d117164 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWPF_sample/WSClientWPF_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWPF_sample/WSClientWPF_sample.csproj @@ -46,7 +46,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin2_sample/WSClientWin2_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin2_sample/WSClientWin2_sample.csproj index e8e1e15b6..ab35da905 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin2_sample/WSClientWin2_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin2_sample/WSClientWin2_sample.csproj @@ -26,7 +26,7 @@ - + diff --git a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin_sample/WSClientWin_sample.csproj b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin_sample/WSClientWin_sample.csproj index 0331f35b4..fffe74349 100644 --- a/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin_sample/WSClientWin_sample.csproj +++ b/root/programs/CS/Samples4NetCore/Legacy/WS_sample/WSClient_sample/WSClientWin_sample/WSClientWin_sample.csproj @@ -48,7 +48,7 @@ - + diff --git a/root/programs/CS/y_Build_TestCode.bat b/root/programs/CS/y_Build_TestCode.bat index 7b4d0cda1..b50eed96a 100644 --- a/root/programs/CS/y_Build_TestCode.bat +++ b/root/programs/CS/y_Build_TestCode.bat @@ -1,4 +1,4 @@ -@rem -------------------------------------------------- +@rem -------------------------------------------------- @rem TestCode -> TestCodeFx, TestCodeCore @rem -------------------------------------------------- echo | call y_Build_TestCode_Public.bat diff --git a/root/programs/CS/y_Build_TestCode_Batch.bat b/root/programs/CS/y_Build_TestCode_Batch.bat index 96982fffb..fe56ef025 100644 --- a/root/programs/CS/y_Build_TestCode_Batch.bat +++ b/root/programs/CS/y_Build_TestCode_Batch.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat @rem -------------------------------------------------- @rem Batch build of SimpleBatch. @rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Tests\TestBatch\SimpleBatch\SimpleBatch.sln" +..\nuget.exe restore "Frameworks\Tests\TestBatch\SimpleBatch\SimpleBatch.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tests\TestBatch\SimpleBatch\SimpleBatch.sln" dotnet restore "Frameworks\Tests\TestBatch\SimpleBatchCore\SimpleBatchCore.sln" diff --git a/root/programs/CS/y_Build_TestCode_Public.bat b/root/programs/CS/y_Build_TestCode_Public.bat index de5e2cbda..799bab923 100644 --- a/root/programs/CS/y_Build_TestCode_Public.bat +++ b/root/programs/CS/y_Build_TestCode_Public.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,11 +18,11 @@ call %CURRENT_DIR%z_Common.bat @rem -------------------------------------------------- @rem Batch build of TestCode. @rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Tests\TestCode\TestCodeFx48.sln" +..\nuget.exe restore "Frameworks\Tests\TestCode\TestCodeFx48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tests\TestCode\TestCodeFx48.sln" -dotnet restore "Frameworks\Tests\TestCode\TestCodeCore80.sln" -dotnet msbuild %COMMANDLINE% "Frameworks\Tests\TestCode\TestCodeCore80.sln" +dotnet restore "Frameworks\Tests\TestCode\TestCodeCore100.sln" +dotnet msbuild %COMMANDLINE% "Frameworks\Tests\TestCode\TestCodeCore100.sln" @echo -------------------------------------------------- @echo Test the TestCodeFx(48). diff --git a/root/programs/CS/y_Build_TestCode_SecCUI.bat b/root/programs/CS/y_Build_TestCode_SecCUI.bat index a3ddb87b5..3b237e051 100644 --- a/root/programs/CS/y_Build_TestCode_SecCUI.bat +++ b/root/programs/CS/y_Build_TestCode_SecCUI.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -23,7 +23,7 @@ cd "Frameworks\Tests\EncAndDecUtilCUI" call copy_cert.bat cd %CURRENTDIR% -..\nuget.exe restore "Frameworks\Tests\EncAndDecUtilCUI\EncAndDecUtilCUIFx48.sln" +..\nuget.exe restore "Frameworks\Tests\EncAndDecUtilCUI\EncAndDecUtilCUIFx48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tests\EncAndDecUtilCUI\EncAndDecUtilCUIFx48.sln" dotnet restore "Frameworks\Tests\EncAndDecUtilCUI\EncAndDecUtilCUICore100.sln" diff --git a/root/programs/CS/y_Build_TestCode_SecGUI.bat b/root/programs/CS/y_Build_TestCode_SecGUI.bat index 46ee8d078..55eb45e16 100644 --- a/root/programs/CS/y_Build_TestCode_SecGUI.bat +++ b/root/programs/CS/y_Build_TestCode_SecGUI.bat @@ -1,4 +1,4 @@ -setlocal +setlocal @rem -------------------------------------------------- @rem Turn off the echo function. @@ -18,7 +18,7 @@ call %CURRENT_DIR%z_Common.bat rem -------------------------------------------------- rem Batch build of EncAndDecUtil. rem -------------------------------------------------- -..\nuget.exe restore "Frameworks\Tests\EncAndDecUtil\EncAndDecUtil48.sln" +..\nuget.exe restore "Frameworks\Tests\EncAndDecUtil\EncAndDecUtil48.sln" %NUGET_MSBUILD% %BUILDFILEPATH% %COMMANDLINE% "Frameworks\Tests\EncAndDecUtil\EncAndDecUtil48.sln" pause diff --git a/root/programs/CS/z_Common.bat b/root/programs/CS/z_Common.bat index 7646fdcb0..192521702 100644 --- a/root/programs/CS/z_Common.bat +++ b/root/programs/CS/z_Common.bat @@ -1,4 +1,4 @@ -@rem -------------------------------------------------- +@rem -------------------------------------------------- @rem Execution of the common processing. @rem -------------------------------------------------- @@ -51,11 +51,69 @@ echo BUILDFILEPATH4.0 %BUILDFILEPATH4.0% echo BUILDFILEPATH15 %BUILDFILEPATH15% echo BUILDFILEPATH16 %BUILDFILEPATH16% echo BUILDFILEPATH17 %BUILDFILEPATH17% -echo BUILDFILEPATH17 %BUILDFILEPATH18% +echo BUILDFILEPATH18 %BUILDFILEPATH18% + +@rem -------------------------------------------------- +@rem vswhere による MSBuild の解決(エディション非依存) +@rem 上記の固定パスは Community しか探さないため、 +@rem Professional / Enterprise / BuildTools でも解決できるようにする。 +@rem -------------------------------------------------- +set VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +set BUILDFILEPATH= + +if exist %VSWHERE% ( + for /f "usebackq tokens=*" %%i in ( + `%VSWHERE% -latest -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe` + ) do set BUILDFILEPATH="%%i" +) + +@rem -------------------------------------------------- +@rem フォールバック(vswhere が無い / 解決できない場合) +@rem -------------------------------------------------- +if not defined BUILDFILEPATH set BUILDFILEPATH=%BUILDFILEPATH18% +if not defined BUILDFILEPATH set BUILDFILEPATH=%BUILDFILEPATH17% +if not defined BUILDFILEPATH set BUILDFILEPATH=%BUILDFILEPATH16% -set BUILDFILEPATH=%BUILDFILEPATH18% echo BUILDFILEPATH %BUILDFILEPATH% +@rem -------------------------------------------------- +@rem 未検出チェック +@rem (空のまま進むと "/p:Configuration=..." が先頭コマンドとして +@rem  実行され、原因が分かりにくいエラーになるため、ここで止める。) +@rem -------------------------------------------------- +if not defined BUILDFILEPATH ( + echo [ERROR] MSBuild.exe が見つかりません。 + echo Visual Studio または Build Tools のインストール状況を確認してください。 + exit /b 1 +) + +@rem -------------------------------------------------- +@rem nuget.exe restore に渡す MSBuild の指定 +@rem +@rem nuget.exe は MSBuild を自動検出するが、SQL Server Management Studio など +@rem MSBuild を同梱する別製品が入っていると、そちらを選ぶことがある。 +@rem (例: "MSBuild 自動検出: 'C:\Program Files\Microsoft SQL Server Management +@rem  Studio 22\Release\MSBuild\Current\bin' から MSBuild バージョン ... を使用します。") +@rem +@rem その MSBuild には Web アプリ用の Microsoft.WebApplication.targets が無く、 +@rem また生成される project.assets.json が実際のビルドと噛み合わないため、 +@rem 下記のようなエラーになる。 +@rem error MSB4226: インポートされたプロジェクト "...WebApplications\ +@rem Microsoft.WebApplication.targets" が見つかりませんでした。 +@rem error : Your project file doesn't list 'win' as a "RuntimeIdentifier". +@rem +@rem このため、上で解決した MSBuild のフォルダを明示的に渡す。 +@rem -------------------------------------------------- +for %%i in (%BUILDFILEPATH%) do set MSBUILDDIR=%%~dpi + +@rem 末尾の \ を除去する(-MSBuildPath "...\" は \" が +@rem エスケープと解釈され、引数が壊れるため)。 +if defined MSBUILDDIR set MSBUILDDIR=%MSBUILDDIR:~0,-1% + +set NUGET_MSBUILD=-MSBuildPath "%MSBUILDDIR%" + +echo NUGET_MSBUILD %NUGET_MSBUILD% + @echo -------------------------------------------------- @echo The choice of build configuration (Debug / Release). @echo BUILD_CONFIG は 特定の構成(Debug や Release)を指定 diff --git a/root/programs/CS/z_Common2.bat b/root/programs/CS/z_Common2.bat index 4aa58775c..4d9da6253 100644 --- a/root/programs/CS/z_Common2.bat +++ b/root/programs/CS/z_Common2.bat @@ -1,7 +1,28 @@ -@rem -------------------------------------------------- +@rem -------------------------------------------------- @rem Execution of the common processing. @rem -------------------------------------------------- +@rem ************************************************** +@rem [経緯] 本バッチは z_Common.bat の devenv 版である。 +@rem MSBuild.exe ではエラーになるが devenv.com では通る、という +@rem ケースが散在していた時期に、ビルド ツールを devenv.com へ +@rem 差し替えるために用意された。 +@rem z_Common.bat と同じインターフェイス(%BUILDFILEPATH% と +@rem %COMMANDLINE%)を提供するため、呼び出し側の bat は +@rem call するファイルを差し替えるだけで切り替えられる。 +@rem ※ そのため COMMANDLINE は devenv 構文の "/build <構成>" であり、 +@rem MSBuild 構文の "/p:Configuration=<構成>" ではない。 +@rem +@rem [注意] 現在は未使用であり、かつこのままでは動作しない。 +@rem ・リポジトリ内に z_Common2.bat を呼び出すバッチは存在しない。 +@rem ・"set BUILDFILEPATH10.0 =..." は "=" の前に空白があるため、 +@rem 変数名に末尾の空白が含まれてしまう。 +@rem ・"set BUILDFILEPATH=BUILDFILEPATH10.0" は "%" が抜けているため、 +@rem パスではなく文字列そのものを代入している。 +@rem 通常は z_Common.bat(MSBuild 版)を使用すること。 +@rem 再び devenv でのビルドが必要になった場合は、上記を修正したうえで使用する。 +@rem ************************************************** + @rem -------------------------------------------------- @rem Set Program Files path @rem -------------------------------------------------- diff --git a/root/programs/CompareResult.ps1 b/root/programs/CompareResult.ps1 new file mode 100644 index 000000000..db5b444e3 --- /dev/null +++ b/root/programs/CompareResult.ps1 @@ -0,0 +1,179 @@ +<# +.SYNOPSIS + 単体テストの実行結果を、同梱の期待結果ファイルと比較して合否を判定する。 + +.DESCRIPTION + 従来「diff で目視」していた判定を機械化するためのスクリプト。 + + 期待結果ファイルと実行結果には、実行のたびに変わる値(日時・処理時間・乱数・ + 署名値・パス等)が含まれるため、素の diff では必ず差分が出る。 + 本スクリプトはそれらを正規化したうえで比較し、残った差分だけを報告する。 + + 正規化しても残る差分は「実質的な差分」であり、次のいずれかを意味する。 + ・退行(コードの不具合) + ・期待結果ファイルの陳腐化 + ・テスト データの汚染(DB のレコードが増減している等) + +.PARAMETER Expected + 期待結果ファイルのパス。 + +.PARAMETER Actual + 実行結果ファイルのパス。 + +.PARAMETER SkipLog4netTrace + log4net の内部トレース("log4net: " で始まる行)を比較対象から除外する。 + 設定内容の確認が目的でなければ、除外した方が判定が読みやすい。 + +.PARAMETER ShowAll + 差分の全件を表示する(既定は先頭 20 件)。 + +.EXAMPLE + .\CompareResult.ps1 -Expected TestCode\Result48.txt -Actual out\TestCode48.txt + +.EXAMPLE + .\CompareResult.ps1 -Expected TestBatch\ResultSimpleBatch48.txt ` + -Actual out\TestBatch48.txt -SkipLog4netTrace + +.NOTES + 作成者 :玄人 幸道 + 更新履歴 : + 日時 更新者 内容 + ---------- ---------------- ------------------------------------------------- + 2026/08/01 玄人 幸道 新規作成(リリース ワークのエージェント化) +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)][string]$Expected, + [Parameter(Mandatory = $true)][string]$Actual, + [switch]$SkipLog4netTrace, + [switch]$ShowAll, + # 判定結果をオブジェクトとして出力する(呼び出し元での集計用)。 + # 画面表示は Write-Host で行っておりパイプラインに乗らないため、 + # 件数を機械的に受け取りたい場合はこれを指定する。 + [switch]$PassThru +) + +# ------------------------------------------------------------------ +# 正規化ルール +# ------------------------------------------------------------------ +# 実行のたびに変わる値を、比較前にプレースホルダへ置き換える。 +# ここに無いものが差分として残る=実質的な差分、という設計。 +$normalizers = @( + # 日時(log4net の ConversionPattern : yyyy/MM/dd HH:mm:ss,fff) + @{ Name = '日時'; Pattern = '\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2},\d{3}'; Replace = '' } + # 日時(Dao 生成物のヘッダ等 : yyyy/M/d) + @{ Name = '日付'; Pattern = '\d{4}/\d{1,2}/\d{1,2}'; Replace = '' } + # 処理時間(フレームワークのアクセス ログ) + # ※ net48 は 2 項目、.NET (Core) は 2 項目目が空になることがあるため、 + # 「数値,数値」「数値,」の両方を吸収する。 + @{ Name = '処理時間'; Pattern = '(?<=\],)\d+,\d*(?=,\[commandText\])'; Replace = '' } + @{ Name = '処理時間(末尾)'; Pattern = '(?<=%-?,)\d+,\d*\s*$'; Replace = '' } + # 絶対パス(実行環境に依存する) + @{ Name = 'パス'; Pattern = '[A-Za-z]:\\\\[^\s,]+'; Replace = '' } + @{ Name = 'パス(単一)'; Pattern = '[A-Za-z]:\\[^\s,]+'; Replace = '' } + # GUID + @{ Name = 'GUID'; Pattern = '[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}'; Replace = '' } + # XML 署名の値(要素で囲まれているため、先に要素単位で潰す) + # ※ 値そのものは Base64 だが、実行のたびに変わるうえ改行を含まないため + # 汎用の Base64 パターンより先に処理する。 + @{ Name = 'XML署名値'; Pattern = '<(SignatureValue|DigestValue|Modulus|Exponent)>[^<]*'; Replace = '<$1>' } + # Base64URL の長い値(JWT・署名・鍵・IV・認証タグ等) + @{ Name = 'Base64URL'; Pattern = '[A-Za-z0-9_\-]{16,}'; Replace = '' } + # Base64 の長い値(鍵・ハッシュ等) + @{ Name = 'Base64'; Pattern = '[A-Za-z0-9+/]{16,}={0,2}'; Replace = '' } + # スレッド ID(実行ごとに変わり得る) + @{ Name = 'スレッドID'; Pattern = '(?<=\],)\[\d+\](?=,)'; Replace = '[]' } +) + +function Normalize([string[]]$lines) +{ + $result = New-Object System.Collections.Generic.List[string] + + foreach ($line in $lines) + { + $s = $line + + if ($SkipLog4netTrace -and $s -match '^log4net: ') + { + continue + } + + if ($s.Trim() -eq '') + { + continue + } + + # 非対話実行の副産物を除外する。 + # サンプルは末尾に Console.ReadKey() を持つものがあり、 + # 出力をリダイレクトして実行すると必ず例外で終わる。 + # テスト内容とは無関係なため、比較対象から外す。 + if ($s -match 'Cannot read keys when either application does not have a console' ` + -or $s -match 'ConsolePal\.ReadKey' ` + -or $s -match 'Exception\.ToString\(\) が失敗したため' ` + -or $s -match '^Unhandled exception\.' ` + -or $s -match '^\s+at .+\.Program\.Main\(') + { + continue + } + + foreach ($n in $normalizers) + { + $s = [regex]::Replace($s, $n.Pattern, $n.Replace) + } + + $result.Add($s.TrimEnd()) + } + + return , $result.ToArray() +} + +# ------------------------------------------------------------------ +# 比較 +# ------------------------------------------------------------------ +if (-not (Test-Path $Expected)) { Write-Error "期待結果ファイルが見つかりません : $Expected"; exit 2 } +if (-not (Test-Path $Actual)) { Write-Error "実行結果ファイルが見つかりません : $Actual"; exit 2 } + +# 読み込みは UTF-8 を明示する。 +# 比較対象の *.txt は BOM 無しの UTF-8 だが、Get-Content の既定エンコードは +# PowerShell のエディションで異なる。 +# Windows PowerShell 5.1 … ANSI(日本語環境では Shift_JIS) +# PowerShell 7 … UTF-8 +# 指定しないと 5.1 だけ文字化けし、同じファイルなのに差分が出る。 +$expLines = Normalize (Get-Content $Expected -Encoding UTF8) +$actLines = Normalize (Get-Content $Actual -Encoding UTF8) + +$diff = @(Compare-Object $expLines $actLines -SyncWindow 20) + +Write-Host "" +Write-Host "=== 比較結果 ===" +Write-Host (" 期待 : {0} ({1} 行)" -f $Expected, $expLines.Count) +Write-Host (" 実測 : {0} ({1} 行)" -f $Actual, $actLines.Count) +Write-Host "" + +if ($diff.Count -eq 0) +{ + Write-Host " OK : 正規化後の差分はありません。" -ForegroundColor Green + if ($PassThru) { [pscustomobject]@{ Result = "OK"; DiffCount = 0 } } + exit 0 +} + +Write-Host (" NG : 正規化後も {0} 件の差分があります。" -f $diff.Count) -ForegroundColor Yellow +Write-Host " 退行/期待結果の陳腐化/テスト データの汚染のいずれかを確認してください。" +Write-Host "" + +$show = if ($ShowAll) { $diff } else { $diff | Select-Object -First 20 } +foreach ($d in $show) +{ + $mark = if ($d.SideIndicator -eq '<=') { '期待のみ' } else { '実測のみ' } + $text = $d.InputObject + if ($text.Length -gt 160) { $text = $text.Substring(0, 160) + ' ...' } + Write-Host (" [{0}] {1}" -f $mark, $text) +} + +if (-not $ShowAll -and $diff.Count -gt 20) +{ + Write-Host (" ... 他 {0} 件(全件表示は -ShowAll)" -f ($diff.Count - 20)) +} + +if ($PassThru) { [pscustomobject]@{ Result = "NG"; DiffCount = $diff.Count } } +exit 1 diff --git a/root/programs/RELEASE.md b/root/programs/RELEASE.md new file mode 100644 index 000000000..b8635dd0d --- /dev/null +++ b/root/programs/RELEASE.md @@ -0,0 +1,277 @@ +# RELEASE.md — リリース チェックリスト + +対象: `root/programs/CS`(C# 側) +配置: `root/programs` +本書は、リリース時に何を・どの順で確認し、**どこまでを機械が行い、どこからを人が行うか**を 1 枚にまとめたもの。 + +> **一次情報は本書ではない。** 迷ったら次を見ること。 +> +> | 内容 | 一次情報 | +> |---|---| +> | ビルド構成・バージョン管理 | [`CS/Frameworks/ANALYSIS.md`](CS/Frameworks/ANALYSIS.md) 7 章 | +> | 全ビルドの実行と判定 | [`BUILDING.md`](BUILDING.md) | +> | 単体テストの実行と判定 | [`TESTING.md`](TESTING.md) | +> | サンプルの疎通確認 | [`SMOKETEST.md`](SMOKETEST.md) | +> | NuGet パッケージ化・公開の手順 | [`CS/NuGet/_手順の説明.txt`](CS/NuGet/_手順の説明.txt) | + +--- + +## 1. 全体の流れ + +| # | フェーズ | 手段 | 実施者 | +|---|---|---|---| +| 0 | 準備 | 手作業 | 人(エージェントは充足状況の確認・報告まで) | +| 1 | 検証(ビルド・単体テスト・疎通) | `1_BuildAll.ps1` / `2_RunAllTests.ps1` / `3_SmokeTest.ps1` | **エージェント可** | +| 2 | 検証(UI 系・ツール) | 手作業(GUI 操作) | 人(自動化は見送り。7 節) | +| 3 | パッケージ化 | `CS\0_Release4Nuget.bat` → `_NuGetPack.bat` | エージェント可(**指示があれば**) | +| 4 | 公開 | `_NuGetPush.bat` + Wiki 手順 | **人のみ** | +| 5 | 後始末 | 手作業 | 人(エージェントは差分の報告まで) | + +### エージェントが実行してよい範囲 + +**取り消しにくい・外部に出る・システム設定を変えるものは人が行う。** + +この線引きは `AGENTS.md`(git 操作をしない/公開リポジトリへの投稿は承認を得てから)と同じ考え方。 + +| 人が行うフェーズ | 人が行う理由 | +|---|---| +| 0 準備 | `Start-Service` `aspnet_state` は**システム設定の変更**。DB の初期化も同様。
    エージェントは不足を検知して**対処方法とともに報告する**に留める | +| 2 検証(UI 系) | GUI 操作のため | +| 4 公開 | `_NuGetPush.bat` は**外部公開で取り消しが困難**。かつ API キーを扱う | +| 5 後始末 | revert の確定はワーキング ツリーの検収と同じ扱い | + +フェーズ 1 をエージェントが実行してよいのは、**失敗しても被害が無く、結果がワーキング ツリーに残るだけ**だから。 + +フェーズ 3 は成果物をローカルに作るだけだが、`CS\z_Common.bat` の `DEBUG_TYPE` 変更を伴い、 +フェーズ 4 と地続きのため、**指示があったときだけ**実行する。 + +**フェーズ 1 は 3 本を順に実行するだけで済む。** + +```powershell +cd root\programs +.\1_BuildAll.ps1 # 全ビルド +``` + +```powershell +.\2_RunAllTests.ps1 # 単体テスト +``` + +```powershell +.\3_SmokeTest.ps1 # サンプルの疎通 +``` + +クリーン ビルドから通しで **約 9.5 分**。 +`2_RunAllTests.ps1` と `3_SmokeTest.ps1` は終了コードだけで合否が分かるが、 +`1_BuildAll.ps1` は既知の署名エラーで 1 になるため、内容の確認が要る(3 節)。 + +--- + +## 2. フェーズ 0 : 準備 + +### 環境 + +- [ ] **Visual Studio を閉じた** + … `1_DeleteDir.bat` が `.vs` を削除するため +- [ ] **SQL Server の Northwind に接続できる** +- [ ] **Northwind が初期状態**(`Shippers` 3 件 / `Orders` 830 件) + … 汚れている場合の戻し方は [`TESTING.md`](TESTING.md) 「テスト データの戻し方」 +- [ ] **`Orders2` テーブルが存在する** … Northwind 標準ではない。無ければ + `CS\Samples\Bat_sample\RerunnableBatch_sample\CREATE ORDERS2.sql` を実行 +- [ ] **サービスが開始されている**(`Start-Service`、`aspnet_state`、要管理者権限) + - Start-Service … アプリが 使うデータストア(Dockerコンテナ)を起動、初期化する。 + - aspnet_state … net48 の Web アプリが使うASP.NET 状態サービスを起動する。 +- [ ] **IIS Express がインストールされている** + +### バージョン番号 + +- [ ] **`CS/Frameworks/Infrastructure/Directory.Build.props` の `OpenTouryoVersion` を更新した** + … SDK 形式アセンブリ 7 個と NuGet パッケージの唯一の定義箇所 +- [ ] **net48(旧形式 csproj)の `Properties\AssemblyInfo.cs` を更新した** + … `Directory.Build.props` が効かないため別管理 +- [ ] **`Business` 系は 1.0.0 のまま**であることを確認した + … Public / Framework / Public.Security の 3.0.0 とは意図的に別系統 +- [ ] **nuspec の `` が csproj の `PackageReference` と一致している** + … 依存を増減したら nuspec 側も合わせる。相互依存の版は `$version$` で自動追随 + +> `Directory.Build.props` の XML コメントに `--`(ハイフン 2 個)を書くと +> MSBuild がプロジェクトの読み込みに失敗する。区切り線に使わないこと。 + +--- + +## 3. フェーズ 1 : 検証(自動) + +| スクリプト | 見るもの | 期待値 | 文書 | +|---|---|---|---| +| `1_BuildAll.ps1` | ビルドが通るか | エラー 0 件 | [`BUILDING.md`](BUILDING.md) | +| `2_RunAllTests.ps1` | 出力が前回と同じか | HEAD の `Result*.txt` | [`TESTING.md`](TESTING.md) | +| `3_SmokeTest.ps1` | 起動して想定どおり動くか | 定義側の判定条件 | [`SMOKETEST.md`](SMOKETEST.md) | + +- [ ] **`1_BuildAll.ps1` のエラーが「既知の 1 件」だけである** + … `-SkipClean` は**使わない**。前回の成果物が残っていると通ったように見える +- [ ] **`2_RunAllTests.ps1` が終了コード 0**(6 ケース) +- [ ] **`3_SmokeTest.ps1` が終了コード 0**(18 件) + +> **`1_BuildAll.ps1` は現状ここで終了コード 1 になる。** +> `WSClnt_sample (net48)` の ClickOnce 署名エラー(`MSB3482`)が残るため。 +> **終了コードだけで判断せず、エラー一覧が下記 1 件だけであることを確認すること**(4 節)。 +> +> ``` +> [WSClnt_sample (net48)] ... error MSB3482: 署名中にエラーが発生しました: +> ... WSClientWinCone_sample.exe の署名に失敗しました。 +> SignTool Error: No certificates were found that met all the given criteria. +> ``` +> +> 証明書をストアに入れた環境では 0 になる。 + +所要時間の実測(クリーン ビルドから通しで **約 9.5 分**)。 + +| スクリプト | 所要 | +|---|---| +| `1_BuildAll.ps1`(31 ステップ) | 5.8 分 | +| `2_RunAllTests.ps1`(6 ケース) | 1.3 分 | +| `3_SmokeTest.ps1`(18 件) | 2.4 分 | + +### 順序を守る + +**`1_BuildAll.ps1` → `2_RunAllTests.ps1` → `3_SmokeTest.ps1` の順で行う。** +`1_BuildAll.ps1` はクリーンを行い、`4_Build_CopyAssemblies.bat` がテストとサンプルの +参照先(`Build_net48` / `Build_netcore100`)を更新するため、 +逆順では古いアセンブリを見ることになる。 + +### NG が出たときの切り分け + +| スクリプト | NG の意味 | +|---|---| +| `1_BuildAll.ps1` | コンパイル エラー、または restore の失敗 | +| `2_RunAllTests.ps1` | 退行/期待結果の陳腐化/**テスト データの汚染**のいずれか | +| `3_SmokeTest.ps1` | 起動時の失敗(構成・ネイティブ DLL・前提サービス)が多い | + +`2_RunAllTests.ps1` の「実測のみ/期待のみ」に**件数の差**が出た場合は、 +まずテスト データの汚染を疑う(`TESTING.md` 5 節)。 + +### `Result*.txt` の扱い + +`2_RunAllTests.ps1` はワーキング ツリーの `Result*.txt` を書き換える(従来のバッチ運用と同じ)。 + +**この生 diff を目視してはいけない。** 実行日時が全行に入るため、 +内容が同じでも**ほぼ全行が差分になる**。実測では 6 ファイルで約 2,458 行。 + +```diff +-[2025/11/18 15:19:08,286],[INFO ],[1],,,,----->>,... ++[2026/08/01 22:40:19,772],[INFO ],[1],,,,----->>,... +``` + +**判定は `2_RunAllTests.ps1` の「正規化後の差分」で行う。** それが 0 なら内容は同じ。 +生 diff を読むのは、正規化後に差分が出たときだけでよい。 + +- [ ] 正規化後の差分が 0 であることを確認した +- [ ] `Result*.txt` をコミットするかどうかを判断した + … 内容が変わっていないなら**コミットしなくてよい**(日時だけの差分が積み上がるため)。 + 仕様変更で内容が変わった場合は、新しい基準としてコミットする + +--- + +## 4. フェーズ 2 : 検証(手作業) + +自動化から外した対象。**起動して主要な画面が出ることを確認する。** + +### UI 系サンプル(18 本) + +| 区分 | net48 | net10.0 | +|---|---|---| +| 2 層 C/S | `2CSClientWin_sample`
    `2CSClientWPF_sample`
    `AsyncEvent_sample`
    `CustCtrl_sample`
    `GenDaoAndBatUpd_sample`
    `TimeStamp_sample` | `2CSClientWin_sample`
    `2CSClientWPF_sample`
    `CustCtrl_sample`
    `GenDaoAndBatUpd_sample`
    `TimeStamp_sample` | +| WS クライアント | `WSClientWin_sample`
    `WSClientWPF_sample`
    `WSClientWin2_sample`
    `WSClientWinCone_sample` | `WSClientWin_sample`
    `WSClientWPF_sample`
    `WSClientWin2_sample` | + +- [ ] 2 層 C/S 系(net48 6 本 / net10.0 5 本)が起動し、CRUD 画面が操作できる +- [ ] WS クライアント系(net48 4 本 / net10.0 3 本)が起動する + +> **WS クライアントの疎通には別リポジトリが要る。** +> 呼び先の Web サービスは +> [`OpenTouryoProject/ResourceServerTemplates`](https://github.com/OpenTouryoProject/ResourceServerTemplates) +> へ移設済みで、本リポジトリだけでは接続先が無い。 + +### フレームワーク付属ツール + +| ツール | 確認内容 | +|---|---| +| `DaoGen_Tool`(墨壺) | **GUI 起動のみ**。CUI(`/HELP` `/CUI /MODE ...`)は `3_SmokeTest.ps1` が網羅済み | +| `DPQuery_Tool` | GUI 起動 | +| `EncAndDecUtil` | GUI 起動(CUI 版は `2_RunAllTests.ps1` が網羅済み) | + +- [ ] `DaoGen_Tool` が GUI で起動し、D 層定義・SQL が生成できる + … 生成ロジック自体は CUI 側で自動確認済み。ここで見るのは **GUI が動くこと** +- [ ] `DPQuery_Tool` が GUI で起動する +- [ ] `EncAndDecUtil` が GUI で起動する + +### 既知の環境依存(NG でも可) + +- [ ] `WSClientWinCone_sample` の ClickOnce 署名エラー(`MSB3482`)を確認した + … 拇印で証明書ストアを検索するため、当該証明書が無い環境ではビルドできない。 + **環境依存でありコード側の不具合ではない**([`BUILDING.md`](BUILDING.md) 4 節) + +--- + +## 5. フェーズ 3・4 : パッケージ化と公開 + +手順の一次情報は [`CS/NuGet/_手順の説明.txt`](CS/NuGet/_手順の説明.txt)。 +**ここに書き写すと二重管理になるため、要点と抜けやすい点だけを挙げる。** + +- [ ] `CS\z_Common.bat` の `DEBUG_TYPE` を `full` → **`portable`** に変更した +- [ ] `CS\0_Release4Nuget.bat` を実行した + … `1_DeleteDir` → `2_Build_NuGet_net48` → `1_DeleteDir` → + `2_Build_NuGet_netcore100` → `4_Build_CopyAssemblies` のみ。サンプルはビルドしない +- [ ] `CS\NuGet\_NuGetPack.bat` でパッケージ化した +- [ ] `CS\NuGet\out\sp\_NuGetPush.bat` に API キーを設定し、push した + … 最新は `sp`(シンボル付き)のみでよい +- [ ] Wiki の手順(NuGet 利用リポジトリの参照貼り直し)を実施した + +--- + +## 6. フェーズ 5 : 後始末 + +**revert を忘れやすい。** 特に API キーはリポジトリに残してはならない。 + +- [ ] `CS\z_Common.bat` の `DEBUG_TYPE` を `full` に戻した +- [ ] `CS\NuGet\out\sp\_NuGetPush.bat` を**プレースホルダに戻した** + … コミットされている状態は `nuget.exe SetApiKey [ApiKey]`。実キーを残さない +- [ ] `git status` に意図しない変更が残っていない + … 特に `Result*.txt`(`2_RunAllTests.ps1` が再生成する)と + `CS\Frameworks\Tests\EncAndDecUtilCUI\*.cer` / `*.pfx`(Git 管理外の作業用コピー) + +--- + +## 7. 自動化の範囲と、その理由 + +| 対象 | 自動化 | 理由 | +|---|---|---| +| 全ビルド(31 ステップ) | 済 | 既存バッチを呼ぶだけで済む | +| 単体テスト(6 ケース) | 済 | 期待結果ファイルが既にあり、正規化で機械比較できる | +| バッチ・CLI サンプル(9 件) | 済 | プロセス実行のみ。DB 疎通まで確認できる | +| `DaoGen_Tool` の CUI(6 件) | 済 | #508 で CUI 化。DB → 定義 CSV → Dao・SQL まで通せる | +| Web アプリ(3 件) | 済 | ログインまで通せば認証・セッションまで確認できる | +| **UI 系サンプル(18 本)** | **見送り** | UI Automation が必要。画面定義の変更で壊れやすく維持費が高い。
    通す B 層/D 層は Web 系・バッチ系と重複し、回帰検出力の増分が小さい | +| **GUI ツール(3 本)** | **見送り** | 同上。`DaoGen_Tool` は生成ロジックを CUI 側で確認済みのため、
    手作業で見るのは GUI が起動することだけでよい | +| **Web サービス** | **不可** | 本リポジトリにホストが無い(別リポジトリへ移設済み) | + +**自動化した対象が「起動する」ことは、手作業側の確認範囲を狭める。** +`DaoGen_Tool` は CUI で生成ロジックまで確認できるようになったため、 +GUI 側で見るのは画面が動くことだけになった。 + +--- + +## 8. エージェント向け作業チェックリスト + +- [ ] `AGENTS.md` のポリシー遵守(**git 操作をしない**) + … 検証で `Result*.txt` が書き換わるが、コミットの要否とタイミングは人が判断する +- [ ] 検証は **`1_BuildAll.ps1` → `2_RunAllTests.ps1` → `3_SmokeTest.ps1` の順**(3 節) +- [ ] `1_BuildAll.ps1` に `-SkipClean` を付けない(リリース判定では前回成果物を残さない) +- [ ] **NG を「既知」で片付けない。** 既知として扱ってよいのは + `WSClientWinCone_sample` の署名エラーと NuGet 脆弱性警告のみ(4 節・[`BUILDING.md`](BUILDING.md) 3 節) +- [ ] `2_RunAllTests.ps1` の NG は、退行/期待結果の陳腐化/テスト データの汚染を切り分けてから報告 +- [ ] **前提サービス・DB の状態を勝手に変えない。** 不足は対処方法とともに報告する + (`3_SmokeTest.ps1` が `aspnet_state` を自動起動しないのと同じ理由) +- [ ] **フェーズ 1(検証)は自分で実行してよい。** フェーズ 0・2・4・5 は人が行う(1 節) +- [ ] **公開(`_NuGetPush.bat`)は実行しない。** 外部公開で取り消しが困難、かつ API キーを扱う。 + パッケージ化(フェーズ 3)は**指示があったときだけ** +- [ ] Issue のクローズ・ラベル変更は**人が行う**。エージェントは提案に留める +- [ ] 後始末(6 節)の revert 漏れが無いか `git status` で確認して報告 diff --git a/root/programs/SMOKETEST.md b/root/programs/SMOKETEST.md new file mode 100644 index 000000000..6aae453d5 --- /dev/null +++ b/root/programs/SMOKETEST.md @@ -0,0 +1,366 @@ +# SMOKETEST.md — サンプルの疎通確認 + +対象: `root/programs/CS`(C# 側) +配置: `root/programs` +本書は、リリース時に行っていた「サンプルを幾つか見繕って手動で疎通を行う」を、 +**合否が出る形に機械化**するための手順と判定基準を記述する(#513 段階 3)。 + +--- + +## 1. 使い方 + +```powershell +cd root\programs + +# 全対象の疎通を確認する +.\3_SmokeTest.ps1 + +# 一部だけ(動作確認用) +.\3_SmokeTest.ps1 -Only "net48" +.\3_SmokeTest.ps1 -Only "Rerunnable" -SkipBuild +``` + +終了コードは `0` = 全対象 OK、`1` = NG あり。 + +| オプション | 内容 | +|---|---| +| `-Only <文字列>` | 対象名の部分一致で絞る | +| `-SkipBuild` | ビルドを省略し、既存のバイナリで疎通のみ行う | +| `-OutputDir <パス>` | ログの保存先(既定 `%TEMP%\OpenTouryoSmokeTest`) | + +--- + +## 2. 段階 1・2 との違い + +| | 見るもの | 期待値 | +|---|---|---| +| `1_BuildAll.ps1`(段階 2) | ビルドが通るか | エラー 0 件 | +| `2_RunAllTests.ps1`(段階 1) | 出力が前回と同じか | HEAD の `Result*.txt` | +| **`3_SmokeTest.ps1`(段階 3)** | **起動して想定どおり動くか** | **定義側に書いた判定条件** | + +段階 1 は回帰テスト、段階 3 は疎通テストで、目的が違う。 +疎通テストは期待結果ファイルを持たず、判定条件を `3_SmokeTest.ps1` の対象定義に書く。 + +**実行順は `1_BuildAll.ps1` → `2_RunAllTests.ps1` → `3_SmokeTest.ps1`。** +リリース時の作業全体は [`RELEASE.md`](RELEASE.md) を参照。 + +--- + +## 3. 対象(18 件) + +### バッチ(8 件) + +| 対象 | 判定 | +|---|---| +| `SimpleBatch_sample` (net48 / net10.0) | `〇件のデータがあります` が出力される | +| `RerunnableBatch_sample` (net48 / net10.0) | `Orders2` の件数が `Orders` と一致する | +| `RerunnableBatch_sample2` (net48 / net10.0) | 同上 | +| `RerunnableBatch_sample3` (net48 / net10.0) | 同上 | + +`RerunnableBatch` 系は `Orders`(830 件) を読み `Orders2` へ INSERT する。3 本の違いは +INSERT の方法(1 件ずつ/SQL 連結/INSERT 文組み立て)で、いずれも結果は同じになる。 + +**実行前に `Orders2` を空にする必要がある。** `OrderID` が主キーのため、 +残っていると重複で落ちる。スクリプトが `DELETE FROM [Orders2]` を行ってから実行する。 +実行後は 830 件=初期状態に戻るため、後始末は不要。 + +### CLI(1 件) + +| 対象 | 判定 | +|---|---| +| `Simple_CLI` (net10.0) | `cmd1 --an-int 123` が `Sub command cmd1: 123` を出力する | + +net48 版は `System.CommandLine` / `Sharprompt` の .NET Framework サポート終了により +ドロップされている(`5_Build_CLI_sample.bat` 参照)。 +`interactive` サブコマンドは対話プロンプトを使うため対象外。 + +### DaoGen_Tool(墨壺)の CUI モード(6 件) + +#508 で追加された CUI。net48 / net10.0 それぞれ 3 件。 + +> **ツール自体の使い方は +> [`CS/Frameworks/Tools/DaoGen_Tool/README.md`](CS/Frameworks/Tools/DaoGen_Tool/README.md) が一次情報。** +> 実行ファイルの場所、ヘルプの出し方、エージェントが踏みやすい罠を記載している。 + +| 対象 | 判定 | +|---|---| +| `/HELP` | ヘルプの見出しが出力される | +| `/CUI /MODE DAODEFGEN` | DB のスキーマから定義 CSV が生成され、対象テーブルが含まれる | +| `/CUI /MODE DAOSQLGEN` | 定義 CSV から Dao(`.cs`)・動的 SQL(`.xml`)・静的 SQL(`.sql`) が生成される | + +**2 モードは連続して実行する。** `DAODEFGEN` が出力した定義 CSV を +`DAOSQLGEN` の入力に使うため、ツール単体ではなく +「DB → 定義 → 生成」の一連の流れを確認できる。 + +対象テーブルは `Shippers,Orders` の 2 つに絞っている。 +全テーブルを回しても時間がかかるだけで、疎通としては同じことを見ているため。 + +生成先は `%TEMP%\OpenTouryoSmokeTest\daogen_*`。 +実行前に前回の生成物を消す。残っていると「生成された」の判定が甘くなる。 + +> **GUI 側の確認は手作業に残る。** 引数なしで起動すると `Application.Run(new Form1())` になる。 + +#### パス区切りの注意 + +コマンドライン解析(`StringVariableOperator.GetCommandArgs`)は +**`\` をエスケープ文字として扱う**ため、パスの区切りは `/` にする。 + +``` +OK : /OUTPUT "C:/temp/out" +OK : /OUTPUT "C:\\temp\\out" +NG : /OUTPUT "C:\temp\out" ← \ が消える +``` + +ツール自身の `/HELP` にも記載されている。 + +#### 標準出力の捕捉 + +`DaoGen_Tool` は `WinExe` で、CUI 時は `AttachConsole(-1)` でコンソールに接続する。 +このため**リダイレクトの方法によって出力が取れない**。 + +| 方法 | 結果 | +|---|---| +| PowerShell の `& $exe ... *>&1 \| Out-File` | **取れる**(68 行) | +| `cmd /c "... > file"` | 取れない(0 行) | + +`3_SmokeTest.ps1` は前者で実行している。 + +### Web アプリ(3 件) + +| 対象 | ホスト | 認証の実装 | 判定 | +|---|---|---|---| +| `MVC_Sample` (net48) | IIS Express | FormsAuthentication | ログイン後 `/Crud1/Index` が 200 | +| `WebForms_Sample` (net48) | IIS Express | FormsAuthentication | ログイン後 `menu.aspx` が 200 | +| `MVC_Sample` (net10.0) | Kestrel | Cookie 認証 | ログイン後 `/Crud1/Index` が 200 | + +**3 つとも確認の深さを揃えている。** 入口ページが 200 を返すだけでは +ホスティングと構成しか確認できないため、いずれも**ログインを通し、 +認証が要る画面に到達できること**まで見る。 + +1. ログイン画面を GET … 画面が出ること。ページが発行した状態を取り出す + (MVC は `__RequestVerificationToken`、WebForms は `__VIEWSTATE` 等) +2. ログインを POST … 偽造防止の検証を通ること +3. 認証が要る画面を GET … **未認証なら 302 になるので、200 なら認証が通っている** + +これでホスティング・構成・ルーティング・認証・セッションまでを一度に確認できる。 +いずれのサンプルも「ユーザー名が空でなければ認証する」実装のため、資格情報は不要。 + +> **未認証時に 302 が返ることは実測で確認済み。** 200 が偶然でないことの裏付けになる。 +> +> ``` +> MVC_Sample (net48) 未認証で /Crud1/Index → 302 +> WebForms_Sample 未認証で /Aspx/start/menu.aspx → 302 +> ``` + +`WebForms_Sample` は `Web.config` の `` で全画面が要認証になっており、 +ログイン後は `` の画面へ遷移する。 +ポストバックには画面が発行した `__VIEWSTATE` / `__VIEWSTATEGENERATOR` / `__EVENTVALIDATION` を +そのまま返す必要があり、コントロール名はマスタ ページ配下のため +`ctl00$ContentPlaceHolder_A$` が付く。 + +### 対象外 + +| 対象 | 理由 | +|---|---| +| `2CS_sample` 系(11 本) | WinForms / WPF。UI Automation が必要で、画面変更に弱く維持費が高い | +| `WSClient_sample` 系(7 本) | 同上 | +| Web サービス(`ASPNETWebService`) | **別リポジトリへ移設済み**。本リポジトリにホストが無い | + +`CS/Samples/WS_sample/WSServer_sample` はクラス ライブラリ(B層・D層)で、 +これを載せる Web サービスは +[`OpenTouryoProject/ResourceServerTemplates`](https://github.com/OpenTouryoProject/ResourceServerTemplates) +へ移設されている。このため本リポジトリだけでは HTTP 疎通ができない。 + +WinForms / WPF 系は、リリース チェックリスト(段階 4)の**手作業項目**として残す。 + +--- + +## 4. 前提条件 + +- **SQL Server の Northwind に接続できる**こと + - 接続文字列は `CS\Samples\Bat_sample\SimpleBatch_sample\App.config` の + `ConnectionString_SQL` を読む。ここで別途ハードコードすると追随できなくなるため +- **`Orders2` テーブルが存在する**こと + - Northwind 標準ではない。無い場合は + `CS\Samples\Bat_sample\RerunnableBatch_sample\CREATE ORDERS2.sql` を実行する +- **IIS Express** がインストールされていること(net48 の Web アプリ) +- **ASP.NET 状態サービスが開始されている**こと(net48 の Web アプリ) + +### ASP.NET 状態サービス + +`MVC_Sample` / `WebForms_Sample` の `Web.config` は `StateServer` を使う。 + +```xml + +``` + +サービスが止まっていると、ログインの POST が **500** になる。 + +``` +System.Web.HttpException: セッション状態要求をセッション状態サーバーに対して作成できませんでした。 +``` + +`3_SmokeTest.ps1` は実行前に確認し、止まっていれば「前提未達」として対処方法を示す。 + +```powershell +Start-Service aspnet_state # 管理者権限が必要 +``` + +**スクリプトはサービスを自動起動しない。** システムの状態を変える操作であり、 +リリース判定のために黙って環境を書き換えるべきではないため。 + +--- + +## 5. 判定基準 + +対象ごとに次のいずれかで判定する。 + +| 種別 | 判定 | +|---|---| +| 出力の照合 | 標準出力が `Expect` の正規表現に一致するか | +| 追加検証 | `Verify` のスクリプト ブロックが `$true` を返すか(DB の件数など) | +| Web の疎通 | `Flow` のスクリプト ブロックが `Ok = $true` を返すか | + +いずれの場合も、**出力に未処理例外が含まれていれば NG**。ただし次は除外する。 + +- **`Console.ReadKey()` 由来の例外** + … サンプルは末尾に `Console.ReadKey()` を持つものがあり、出力をリダイレクトすると + 必ず例外で終わる。テスト内容とは無関係 + +--- + +## 6. ビルドについて + +**リポジトリ既定のビルド バッチを呼ぶ。** 理由は `2_RunAllTests.ps1` と同じで、 +`csproj` を直接 MSBuild すると `nuget.exe restore` が行うネイティブ DLL の配置が漏れ、 +**ビルドは成功するのに実行時に落ちる**(`TESTING.md` の「ビルドをバッチに委ねている理由」)。 + +### `1_BuildAll.ps1` の後にバイナリが残らない理由 + +`0_ExecAllBat.bat` は途中で `1_DeleteDir.bat` を繰り返し実行し、 +配下の `bin` / `obj` / `packages` 等を**再帰的に**削除する。 + +``` +… net48 サンプルをビルド … +Clean (core サンプル) ← ここで net48 サンプルの bin も消える +… Core サンプルをビルド … +``` + +このため `1_BuildAll.ps1` の完走後に残るのは最後にビルドされた Core サンプルだけで、 +net48 サンプルのバイナリは残らない。`3_SmokeTest.ps1` が自分でビルドするのはこのため。 + +--- + +## 7. 修正の経緯 : バッチ サンプルが実行時に落ちていた + +着手時、net48 のバッチ サンプル 4 本がすべて起動直後に落ちていた。 + +``` +System.DllNotFoundException + 場所 Microsoft.Data.SqlClient.SNINativeManagedWrapperX64.SNIInitialize(IntPtr) +``` + +原因は、`5_Build_Bat_sample.bat` と `6_Build_WSSrv_sample.bat` に +**`nuget.exe restore` が無かった**こと。`Microsoft.Data.SqlClient` は SNI を +ネイティブ DLL で持つため、restore を経ないと `bin` に配置されない。 + +**ビルドは成功する**ため、段階 2(ビルドの合否判定)では検出できない。 +疎通テストで初めて表面化する種類の不具合である。 + +他の 11 バッチと同じ形式で `nuget.exe restore ... %NUGET_MSBUILD%` を追加した。 + +--- + +## 8. 実行結果の例 + +``` +対象 結果 内容 +---- ---- ---- +SimpleBatch_sample (net48) OK 3件のデータがあります +RerunnableBatch_sample (net48) OK +RerunnableBatch_sample2 (net48) OK +RerunnableBatch_sample3 (net48) OK +SimpleBatch_sample (net10.0) OK 3件のデータがあります +RerunnableBatch_sample (net10.0) OK +RerunnableBatch_sample2 (net10.0) OK +RerunnableBatch_sample3 (net10.0) OK +Simple_CLI (net10.0) OK Sub command cmd1: 123 +DaoGen_Tool /HELP (net48) OK DaoGen_Tool(D層自動生成ツール/墨壺) +DaoGen_Tool DAODEFGEN (net48) OK 生成が完了しました。 +DaoGen_Tool DAOSQLGEN (net48) OK 生成が完了しました。 +DaoGen_Tool /HELP (net10.0) OK DaoGen_Tool(D層自動生成ツール/墨壺) +DaoGen_Tool DAODEFGEN (net10.0) OK 生成が完了しました。 +DaoGen_Tool DAOSQLGEN (net10.0) OK 生成が完了しました。 +MVC_Sample (net48) OK ログイン後 /Crud1/Index = 200 +WebForms_Sample (net48) OK ログイン後 menu.aspx = 200 +MVC_Sample (net10.0) OK ログイン後 /Crud1/Index = 200 + + 全対象 OK +``` + +全 18 件(ビルド 7 バッチ + 疎通 18 件)で **約 2.4 分**。 + +### リダイレクトの扱い + +`Invoke-WebRequest` は `-MaximumRedirection 0` で 3xx を受け取ると、 +`-SkipHttpErrorCheck` を付けていても +「The maximum redirection count has been exceeded」で終了エラーになる。 + +ログイン成功時は `FormsAuthentication` が 302 を返すため、これに該当する。 +`3_SmokeTest.ps1` は `Invoke-Http` で捕まえ、3xx を正常な結果として扱う。 +素の `Invoke-WebRequest` を使うと、**判定は通るのにエラーが表示される**状態になる。 + +--- + +## 9. 対象を追加するとき + +`3_SmokeTest.ps1` の `$targets` に定義を足す。 + +| 項目 | 内容 | +|---|---| +| `Name` | 表示名 | +| `Bat` | ビルドに使うバッチ(`root\programs\CS` 配下) | +| `Exe` | 実行ファイル。`.dll` なら `dotnet` で実行する | +| `Args` | コマンドライン引数 | +| `Pre` | 実行前の準備(スクリプト ブロック) | +| `Expect` | 標準出力に対する正規表現 | +| `Verify` | 追加の検証(スクリプト ブロック) | +| `Kind` | `Web` を指定すると Web アプリ扱い | +| `WebHost` | `IISExpress` または `Kestrel` | +| `Site` / `Port` / `Flow` / `Need` | Web アプリ用 | + +**判定条件は「動いていれば必ず満たす」ものにする。** +実行のたびに変わる値(件数以外の可変値、日時など)を条件に入れると、 +環境差で落ちるだけの脆いテストになる。 + +### `dotnet` への引数の渡し方 + +`/DAP` のように `/` で始まる引数は `--` で区切って渡す必要がある。 +一方 `System.CommandLine` を使う CLI では `--` 以降が未解析トークン扱いになり、 +**サブコマンドが認識されなくなる**。`3_SmokeTest.ps1` は引数を見て自動で切り替える。 + +### PowerShell 5.1 と 7 の両対応 + +**両方で動くこと。** 開発時に `pwsh`(7)だけで確認すると、 +利用者が `powershell.exe`(5.1)で実行したときに落ちる。 + +> **規約の実体は +> [`CS/Frameworks/ANALYSIS.md`](CS/Frameworks/ANALYSIS.md) の 8.4 節**にある。 +> 落とし穴の一覧と対処方法は、そちらを参照すること。 + +本スクリプト群は、次の 4 点を**実際に踏んだ**うえで対処してある。 +同種のスクリプトを追加・変更するときの実例として挙げる。 + +| 事象 | 踏んだ箇所 | +|---|---| +| BOM 無しで構文エラー・文字化け | 5 本すべて(`0_RunAll.ps1` ほか) | +| `Get-Content` の既定エンコード差で、同じファイルなのに差分が出る | `CompareResult.ps1` | +| `-SkipHttpErrorCheck` が 5.1 に無く、HTTP が常に失敗 | `3_SmokeTest.ps1` の `Invoke-Http` | +| `chcp` による画面クリアと、ログの文字化け | 3 本すべて(冒頭でコード ページを切り替え) | + + +### PowerShell から `.bat` を呼ぶときの注意 + +`TESTING.md` と同じく、`NoDefaultCurrentDirectoryInExePath` を解除している。 +解除しないと、バッチ内でパス区切りを含まない名前で起動している exe が動かない。 diff --git a/root/programs/TESTING.md b/root/programs/TESTING.md new file mode 100644 index 000000000..691c4d2a9 --- /dev/null +++ b/root/programs/TESTING.md @@ -0,0 +1,261 @@ +# TESTING.md — 単体テストの実行と判定 + +対象: `root/programs/CS/Frameworks/Tests`(C# 側) +配置: `root/programs` +本書は、リリース時に行っていた「単体テスト スクリプトの実行結果を diff で目視」を、 +**機械判定に置き換える**ための手順と判定基準を記述する(#513 段階 1)。 + +リリース時の作業全体は [`RELEASE.md`](RELEASE.md) を参照。 +実行順は `1_BuildAll.ps1` → `2_RunAllTests.ps1` → `3_SmokeTest.ps1`。 + +--- + +## 1. 使い方 + +```powershell +cd root\programs + +# ビルド バッチを実行し、再生成された結果を HEAD 版と比較して一覧表示する +.\2_RunAllTests.ps1 + +# バッチを実行せず、いま手元にある結果ファイルだけを比較する +.\2_RunAllTests.ps1 -SkipBuild + +# 個別に比較する +.\CompareResult.ps1 -Expected -Actual TestCode\Result48.txt +.\CompareResult.ps1 -Expected -Actual TestBatch\ResultSimpleBatch48.txt -SkipLog4netTrace +``` + +終了コードは `0` = 全 OK、`1` = NG あり、`2` = ファイル無し。 + +--- + +## 2. 何を何と比較しているか + +**従来の運用をそのまま機械化している。** 置き換えたのは最後の「目視」だけ。 + +`y_Build_TestCode*.bat` は「ビルド → テスト実行 → **結果を `Result*.txt` へ出力**」まで行う。 +この `Result*.txt` は Git 管理下にあり、バッチを実行すると上書きされる。 +つまり従来の手順は次のとおりだった。 + +1. バッチを実行して `Result*.txt` を再生成する +2. `git diff` で「前回のリリース時の結果」との差分を目視する + +`2_RunAllTests.ps1` はこの構造を変えず、2 を機械比較に置き換える。 + +| | 実体 | 取得方法 | +|---|---|---| +| **期待値** | HEAD にコミットされている `Result*.txt` | `git show HEAD:`(参照系のみ) | +| **実測値** | バッチが再生成したワーキング ツリーの `Result*.txt` | バッチの実行 | + +> **副作用**: ワーキング ツリーの `Result*.txt` が書き換わる。これは従来のバッチ運用と同じ。 + +**生 `git diff` を目視してはいけない。** 実行日時が全行に入るため、 +内容が同じでも**ほぼ全行が差分になる**(実測で 6 ファイル約 2,458 行)。 + +```diff +-[2025/11/18 15:19:08,286],[INFO ],[1],,,,----->>,... ++[2026/08/01 22:40:19,772],[INFO ],[1],,,,----->>,... +``` + +判定は本スクリプトの**正規化後の差分**で行う。0 なら内容は同じ。 +生 diff を読むのは、正規化後に差分が出たときだけでよい。 +`Result*.txt` のコミットは、内容が変わった(新しい基準にしたい)ときだけでよい。 + +### 対象テスト(6 ケース) + +| テスト | 結果ファイル(=期待値) | ビルド バッチ | 備考 | +|---|---|---|---| +| TestCode (net48) | `TestCode/Result48.txt` | `y_Build_TestCode_Public.bat` | 部品層の総合テスト(約 2,300 行) | +| TestCode (net10.0) | `TestCode/ResultCore100.txt` | 同上 | 同上 | +| SimpleBatch (net48) | `TestBatch/ResultSimpleBatch48.txt` | `y_Build_TestCode_Batch.bat` | **DB 接続あり**(Northwind) | +| SimpleBatch (net10.0) | `TestBatch/ResultSimpleBatchCore100.txt` | 同上 | 同上 | +| EncAndDecUtilCUI (net48) | `EncAndDecUtilCUI/Result48.txt` | `y_Build_TestCode_SecCUI.bat` | 暗号・JWT・XML 署名 | +| EncAndDecUtilCUI (net10.0) | `EncAndDecUtilCUI/ResultCore100.txt` | 同上 | 同上 | + +`EncAndDecUtilCUI/ResultCore100OnLinux.txt` は Linux 実行時の期待結果のため、 +Windows からの `2_RunAllTests.ps1` の対象外。 + +### ビルドをバッチに委ねている理由 + +`csproj` / `sln` を直接 MSBuild してはならない。 +`nuget.exe restore` が行う**ネイティブ DLL の配置が漏れる**ためで、 +ビルドは成功するのに実行時に落ちる、という分かりにくい失敗になる。 + +``` +System.DllNotFoundException + at Microsoft.Data.SqlClient.SNINativeManagedWrapperX64.SNIInitialize(IntPtr) +``` + +`Microsoft.Data.SqlClient` は SNI をネイティブ DLL で持ち、 +`bin\Debug\Microsoft.Data.SqlClient.SNI.x64.dll` 等が必要になる。 +「何をどうビルドするか」の正はバッチ側に置く。 + +### PowerShell から `.bat` を呼ぶときの注意 + +PowerShell は子プロセスに `NoDefaultCurrentDirectoryInExePath=1` を渡す。 +一方バッチは、出力フォルダへ `cd` したうえでパス区切りを含まない名前で実行している。 + +```bat +cd "Frameworks\Tests\TestBatch\SimpleBatch\bin\Debug" +SimpleBatch.exe /Dap SQL ... > ..\..\..\ResultSimpleBatch48.txt +``` + +この変数が効いていると次のようになり、**結果ファイルが空のまま、バッチは成功したように進む**。 + +``` +'SimpleBatch.exe' is not recognized as an internal or external command, +``` + +`2_RunAllTests.ps1` は、バッチを直接実行した場合と同じ条件にするため、この変数を解除している。 + +--- + +## 3. 前提条件 + +- **Frameworks をビルド済み**であること(`Build_net48` / `Build_netcore100` が存在) +- **SQL Server の Northwind に接続できる**こと(SimpleBatch が使用) +- **Northwind のテスト データが標準状態**であること(後述の「4. テスト データ」) + +### テスト証明書について + +`EncAndDecUtilCUI` の csproj は `*.cer` / `*.pfx` を `CopyToOutputDirectory` しているため、 +**これらが無いとビルドが `MSB3030` で失敗する**。 + +これらは **Git 管理外の作業用コピー**であり、**正本はリポジトリ内の +`root/files/resource/X509/`**(10 件が Git 管理下)にある。 + +`y_Build_TestCode_SecCUI.bat` は先頭で `copy_cert.bat` を呼ぶが、こちらは `C:\root\files\...` +を参照するため、リポジトリだけを clone した環境では配置できない。 +`2_RunAllTests.ps1` はリポジトリ内の正本から不足を**自動で配置**するため、手動操作は不要。 +個別にビルドする場合のみ、次のいずれかを実行する。 + +```powershell +# リポジトリ内の正本から配置(推奨・配置場所に依存しない) +Copy-Item ..\..\..\..\files\resource\X509\SHA*.??? EncAndDecUtilCUI\ + +# あるいは同梱のバッチ(C:\root\files\resource\X509\ を参照する) +cd EncAndDecUtilCUI +.\copy_cert.bat +``` + +`copy_cert.bat` は `C:\root\files\...` を参照するが、そちらは Samples の**実行時**要件であり、 +単体テストのビルドには不要。リポジトリ内の正本から取る方が確実。 + +--- + +## 4. なぜ「目視」だったのか(正規化の必要性) + +期待結果と実行結果には、**実行のたびに変わる値**が多数含まれる。 +そのため素の diff では必ず差分が出る。実測値は次のとおり。 + +| テスト | 素の diff | 正規化後 | +|---|---|---| +| TestCode (net48) | 10 件 | **0 件** | +| TestCode (net10.0) | 11 件 | **0 件** | +| EncAndDecUtilCUI (net48) | 52 件 | **0 件** | +| EncAndDecUtilCUI (net10.0) | 52 件 | **0 件** | + +`CompareResult.ps1` は次を正規化してから比較する。 + +| 種別 | 例 | +|---|---| +| 日時 | `[2026/08/01 14:39:50,027]` → `` | +| 処理時間 | アクセス ログ末尾の `234,125` → `` | +| 絶対パス | `C:\OpenTouryo\...` → `` | +| GUID | → `` | +| XML 署名値 | `...` → `` | +| Base64URL | JWT・JWE の IV・認証タグ・鍵 → `` | +| Base64 | 鍵・ハッシュ → `` | + +加えて、次の行は比較対象から除外する。 + +- **空行** +- **`-SkipLog4netTrace` 指定時の `log4net: ` 行** + … `TestBatch` は 149 行中 145 行が log4net の内部トレースで、判定は残り 4 行 +- **非対話実行の副産物** + … サンプルは末尾に `Console.ReadKey()` を持つものがあり、 + 出力をリダイレクトすると必ず例外で終わる。テスト内容とは無関係 + +--- + +## 5. 判定基準 + +**正規化後に残った差分は「実質的な差分」**であり、次のいずれかを意味する。 + +1. **退行** … コードの不具合。要調査 +2. **期待結果ファイルの陳腐化** … 仕様変更に追随していない。期待結果を更新する +3. **テスト データの汚染** … DB のレコードが増減している。データを戻す + +`3` の実例(2026-08-01 に発生。復旧済み): + +``` +SimpleBatch (net48 / net10.0) + [実測のみ] 4件のデータがあります + [期待のみ] 3件のデータがあります +``` + +Northwind の `Shippers` は標準で 3 件だが、`ShipperID=4` に `Speedy Express` の重複が +存在していた。CRUD サンプルの「追加」操作で挿入されたものと見られる。 + +このように、**件数などテスト対象の出力そのものは正規化してはならない**。 +正規化すると、退行とデータ汚染のいずれも検出できなくなる。 + +**テスト データを汚す操作を行った後は、DB を戻してから単体テストを実行すること。** + +```sql +-- 確認(標準は 3 件) +SELECT ShipperID, CompanyName FROM Shippers ORDER BY ShipperID; +``` + +### テスト データの戻し方 + +DB コンテナは**永続ボリュームを使用していない**(`docker-compose.yml` の +`./sqlserver/mssql-db:/var/opt/mssql` はコメントアウト)。 +Northwind は起動のたびに `start-up.sh` が再作成するため、 +**コンテナを作り直せば初期データに戻る**。 + +`LocalServicesOnDocker` の PowerShell 版スクリプトを使用する +(**DB の初期化完了待ちを行う**ため、`.bat` 版よりテスト用途に適している)。 + +| 環境 | 使用するスクリプト | +|---|---| +| Rancher Desktop 導入時(Windows から `docker` が使える) | `Stop-Services.ps1` → `Start-Services.ps1` | +| WSL2 内の Docker を使う場合 | `Stop-Services_wsl2.ps1` → `Start-Services_wsl2.ps1` | + +```powershell +cd +.\Stop-Services.ps1 # docker compose down(コンテナを破棄) +.\Start-Services.ps1 # docker compose up -d + DB 初期化完了待ち +``` + +> **`docker restart` では戻らない。** 同一コンテナが再開されるだけで書き込み層が保持されるため。 +> コンテナの破棄(`down`)と再作成(`up`)が必要。 +> なお compose には `restart: always` が指定されているため、ホスト再起動でも戻らない。 + +初期化完了待ちを省略したい場合は `-NoWait` を指定できるが、 +その場合は Northwind のロード完了前にテストが始まり得るため、テスト用途では非推奨。 + +コンテナを作り直さず、個別に戻すこともできる。 + +```sql +DELETE FROM Shippers WHERE ShipperID > 3; +``` + +### 期待結果に含まれる「正常な失敗」 + +`EncAndDecUtilCUI` の期待結果には `False` を含む行が **3 件**含まれる。 +これはプラットフォーム非対応等による既知の失敗であり、**正常**。 +実測でも同数であることを確認すること(`CompareResult.ps1` は行単位で比較するため自動的に検出される)。 + +--- + +## 6. 正規化ルールを追加するとき + +新しい非決定値が現れた場合は、`CompareResult.ps1` の `$normalizers` に追加する。 + +**追加してよいのは「実行のたびに変わる値」だけ**。 +テスト対象の出力(件数・判定結果・型名など)を正規化してはならない。 +差分を消すために安易にパターンを広げると、退行を検出できなくなる。 + +判断に迷う場合は、**同じ環境で 2 回実行して差分が出る値かどうか**を確認するとよい。 diff --git a/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js new file mode 100644 index 000000000..85a9b1dad --- /dev/null +++ b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.js @@ -0,0 +1,205 @@ +// Unobtrusive Ajax support library for jQuery +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// @version v3.2.6 +// +// Microsoft grants you the right to use these script files for the sole +// purpose of either: (i) interacting through your browser with the Microsoft +// website or online service, subject to the applicable licensing or use +// terms; or (ii) using the files as included with a Microsoft product subject +// to that product's license terms. Microsoft reserves all other rights to the +// files not expressly granted by Microsoft, whether by implication, estoppel +// or otherwise. Insofar as a script file is dual licensed under GPL, +// Microsoft neither took the code under GPL nor distributes it thereunder but +// under the terms set out in this paragraph. All notices and licenses +// below are for informational purposes only. + +/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ +/*global window: false, jQuery: false */ + +(function ($) { + var data_click = "unobtrusiveAjaxClick", + data_target = "unobtrusiveAjaxClickTarget", + data_validation = "unobtrusiveValidation"; + + function getFunction(code, argNames) { + var fn = window, parts = (code || "").split("."); + while (fn && parts.length) { + fn = fn[parts.shift()]; + } + if (typeof (fn) === "function") { + return fn; + } + argNames.push(code); + return Function.constructor.apply(null, argNames); + } + + function isMethodProxySafe(method) { + return method === "GET" || method === "POST"; + } + + function asyncOnBeforeSend(xhr, method) { + if (!isMethodProxySafe(method)) { + xhr.setRequestHeader("X-HTTP-Method-Override", method); + } + } + + function asyncOnSuccess(element, data, contentType) { + var mode; + + if (contentType.indexOf("application/x-javascript") !== -1) { // jQuery already executes JavaScript for us + return; + } + + mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase(); + $(element.getAttribute("data-ajax-update")).each(function (i, update) { + var top; + + switch (mode) { + case "BEFORE": + $(update).prepend(data); + break; + case "AFTER": + $(update).append(data); + break; + case "REPLACE-WITH": + $(update).replaceWith(data); + break; + default: + $(update).html(data); + break; + } + }); + } + + function asyncRequest(element, options) { + var confirm, loading, method, duration; + + confirm = element.getAttribute("data-ajax-confirm"); + if (confirm && !window.confirm(confirm)) { + return; + } + + loading = $(element.getAttribute("data-ajax-loading")); + duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0; + + $.extend(options, { + type: element.getAttribute("data-ajax-method") || undefined, + url: element.getAttribute("data-ajax-url") || undefined, + cache: (element.getAttribute("data-ajax-cache") || "").toLowerCase() === "true", + beforeSend: function (xhr) { + var result; + asyncOnBeforeSend(xhr, method); + result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments); + if (result !== false) { + loading.show(duration); + } + return result; + }, + complete: function () { + loading.hide(duration); + getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments); + }, + success: function (data, status, xhr) { + asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html"); + getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments); + }, + error: function () { + getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments); + } + }); + + options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" }); + + method = options.type.toUpperCase(); + if (!isMethodProxySafe(method)) { + options.type = "POST"; + options.data.push({ name: "X-HTTP-Method-Override", value: method }); + } + + // change here: + // Check for a Form POST with enctype=multipart/form-data + // add the input file that were not previously included in the serializeArray() + // set processData and contentType to false + var $element = $(element); + if ($element.is("form") && $element.attr("enctype") == "multipart/form-data") { + var formdata = new FormData(); + $.each(options.data, function (i, v) { + formdata.append(v.name, v.value); + }); + $("input[type=file]", $element).each(function () { + var file = this; + $.each(file.files, function (n, v) { + formdata.append(file.name, v); + }); + }); + $.extend(options, { + processData: false, + contentType: false, + data: formdata + }); + } + // end change + + $.ajax(options); + } + + function validate(form) { + var validationInfo = $(form).data(data_validation); + return !validationInfo || !validationInfo.validate || validationInfo.validate(); + } + + $(document).on("click", "a[data-ajax=true]", function (evt) { + evt.preventDefault(); + asyncRequest(this, { + url: this.href, + type: "GET", + data: [] + }); + }); + + $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) { + var name = evt.target.name, + target = $(evt.target), + form = $(target.parents("form")[0]), + offset = target.offset(); + + form.data(data_click, [ + { name: name + ".x", value: Math.round(evt.pageX - offset.left) }, + { name: name + ".y", value: Math.round(evt.pageY - offset.top) } + ]); + + setTimeout(function () { + form.removeData(data_click); + }, 0); + }); + + $(document).on("click", "form[data-ajax=true] :submit", function (evt) { + var name = evt.currentTarget.name, + target = $(evt.target), + form = $(target.parents("form")[0]); + + form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []); + form.data(data_target, target); + + setTimeout(function () { + form.removeData(data_click); + form.removeData(data_target); + }, 0); + }); + + $(document).on("submit", "form[data-ajax=true]", function (evt) { + var clickInfo = $(this).data(data_click) || [], + clickTarget = $(this).data(data_target), + isCancel = clickTarget && (clickTarget.hasClass("cancel") || clickTarget.attr('formnovalidate') !== undefined); + evt.preventDefault(); + if (!isCancel && !validate(this)) { + return; + } + asyncRequest(this, { + url: this.action, + type: this.method || "GET", + data: clickInfo.concat($(this).serializeArray()) + }); + }); +}(jQuery)); diff --git a/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js new file mode 100644 index 000000000..ae780ac8a --- /dev/null +++ b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Scripts/jquery.unobtrusive-ajax.min.js @@ -0,0 +1,16 @@ +// Unobtrusive Ajax support library for jQuery +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// @version v3.2.6 +// +// Microsoft grants you the right to use these script files for the sole +// purpose of either: (i) interacting through your browser with the Microsoft +// website or online service, subject to the applicable licensing or use +// terms; or (ii) using the files as included with a Microsoft product subject +// to that product's license terms. Microsoft reserves all other rights to the +// files not expressly granted by Microsoft, whether by implication, estoppel +// or otherwise. Insofar as a script file is dual licensed under GPL, +// Microsoft neither took the code under GPL nor distributes it thereunder but +// under the terms set out in this paragraph. All notices and licenses +// below are for informational purposes only. +!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery); \ No newline at end of file diff --git a/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml index 781f02a0c..91b3a57ea 100644 --- a/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml +++ b/root/programs/VB/Samples/WebApp_sample/MVC_Sample/MVC_Sample/Views/Shared/_Layout.cshtml @@ -69,10 +69,10 @@ @if (User.Identity.IsAuthenticated) { @* 各メニューは、ユーザーが認証されている時だけ表示する *@ -
  • +
  • メニュー1
  • -
  • +
  • メニュー2
  • } diff --git a/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js b/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js index d9584cf27..c0f54afbc 100644 --- a/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js +++ b/root/programs/VB/Samples/WebApp_sample/WebForms_Sample/WebForms_Sample/Scripts/touryo/common.js @@ -44,6 +44,9 @@ //* 2019/03/04 西野 大介 二重送信防止のブラウザ判定処理を修正 //* 2019/03/04 西野 大介 WebForms版とMVC版のDiffを取り易く修正。 //* 2020/03/19 西野 大介 モダン・ブラウザ・サポート(2017/04/20)の制限事項解除 +//* 2026/08/01 玄人 幸道 業務モーダル画面を閉じた際に親画面がPost Backされない問題に対応 +//* (unloadイベントがブラウザ側で無効化されたため、 +//*  window.closedのポーリングによる終了検知を併用する) //********************************************************************************** // --------------------------------------------------------------- @@ -938,11 +941,24 @@ function Fx_CallbackOfBusinessModalScreen() { // --------------------------------------------------------------- function Fx_CallbackOfBusinessModalScreen2() { + // ↓↓↓【追加】↓↓↓ + // unloadイベントとポーリングの両方から呼ばれる可能性があるため、二重実行を防ぐ。 + if (Fx_BusinessPseudoModelDialog === null + || Fx_BusinessPseudoModelDialog === undefined) { + return; + } + // ↑↑↑【追加】↑↑↑ + // イベントを外す if (Fx_BusinessPseudoModelDialog.closed) { // 閉じている。 $(Fx_BusinessPseudoModelDialog).off("unload"); //, Fx_CallbackOfBusinessModalScreen); Fx_BusinessPseudoModelDialog = null; + + // ↓↓↓【追加】↓↓↓ + // 終了検知のポーリングも解除する。 + Fx_ClearWatcherOfBusinessModalScreen(); + // ↑↑↑【追加】↑↑↑ } else { // 閉じていない。 // unloadのCallbackを"再度"仕掛ける。 @@ -1129,8 +1145,61 @@ function Fx_SetCallbackOfBusinessModalScreen() { // --------------------------------------------------------------- function Fx_SetCallbackOfBusinessModalScreen2() { $(Fx_BusinessPseudoModelDialog).on("unload", Fx_CallbackOfBusinessModalScreen); + + // ↓↓↓【追加】↓↓↓ + // unloadイベントは、モダン・ブラウザ側で無効化が進んでおり発火しないことがある + // (Chromeでは document.featurePolicy.allowsFeature("unload") が false になる)。 + // このため、window.closed のポーリングでも子画面の終了を検知する。 + Fx_SetWatcherOfBusinessModalScreen(); + // ↑↑↑【追加】↑↑↑ } +// ↓↓↓【追加】↓↓↓ + +// Business疑似Model(実体はModeless)Screenの終了監視タイマ +var Fx_WatcherOfBusinessPseudoModelDialog = null; + +// --------------------------------------------------------------- +// モダンブラウザ版(window.closedのポーリングによる終了検知を仕掛ける) +// --------------------------------------------------------------- +// 引数 - +// 戻り値 - +// --------------------------------------------------------------- +function Fx_SetWatcherOfBusinessModalScreen() { + + // 多重に仕掛けない。 + Fx_ClearWatcherOfBusinessModalScreen(); + + Fx_WatcherOfBusinessPseudoModelDialog = setInterval( + function () { + if (Fx_BusinessPseudoModelDialog === null + || Fx_BusinessPseudoModelDialog === undefined + || Fx_BusinessPseudoModelDialog.closed) { + + // 閉じられたので、監視を終了して後処理を実行する。 + Fx_ClearWatcherOfBusinessModalScreen(); + Fx_CallbackOfBusinessModalScreen(); + } + }, + TimeLag4BusinessPseudoModelDialog); +} + +// --------------------------------------------------------------- +// モダンブラウザ版(終了検知のポーリングを解除する) +// --------------------------------------------------------------- +// 引数 - +// 戻り値 - +// --------------------------------------------------------------- +function Fx_ClearWatcherOfBusinessModalScreen() { + + if (Fx_WatcherOfBusinessPseudoModelDialog !== null) { + clearInterval(Fx_WatcherOfBusinessPseudoModelDialog); + Fx_WatcherOfBusinessPseudoModelDialog = null; + } +} + +// ↑↑↑【追加】↑↑↑ + //********************************************************************************** // フレームワーク機能(Ajax Extension) //********************************************************************************** diff --git a/root/programs/1_DeleteDir.bat b/root/programs/bak/1_DeleteDir.bat similarity index 100% rename from root/programs/1_DeleteDir.bat rename to root/programs/bak/1_DeleteDir.bat diff --git a/root/programs/1_DeleteFile.bat b/root/programs/bak/1_DeleteFile.bat similarity index 100% rename from root/programs/1_DeleteFile.bat rename to root/programs/bak/1_DeleteFile.bat diff --git a/root/programs/9_CICD.bat b/root/programs/bak/9_CICD.bat similarity index 100% rename from root/programs/9_CICD.bat rename to root/programs/bak/9_CICD.bat diff --git a/root/programs/9_LogMonitoring.ps1 b/root/programs/bak/9_LogMonitoring.ps1 similarity index 100% rename from root/programs/9_LogMonitoring.ps1 rename to root/programs/bak/9_LogMonitoring.ps1 diff --git a/root/programs/BackupCICDLog/z_GrepResult1.bat b/root/programs/bak/BackupCICDLog/z_GrepResult1.bat similarity index 100% rename from root/programs/BackupCICDLog/z_GrepResult1.bat rename to root/programs/bak/BackupCICDLog/z_GrepResult1.bat diff --git a/root/programs/BackupCICDLog/z_GrepResult2.bat b/root/programs/bak/BackupCICDLog/z_GrepResult2.bat similarity index 100% rename from root/programs/BackupCICDLog/z_GrepResult2.bat rename to root/programs/bak/BackupCICDLog/z_GrepResult2.bat diff --git a/root/programs/BackupCICDLog/z_GrepResult3.bat b/root/programs/bak/BackupCICDLog/z_GrepResult3.bat similarity index 100% rename from root/programs/BackupCICDLog/z_GrepResult3.bat rename to root/programs/bak/BackupCICDLog/z_GrepResult3.bat diff --git a/root/programs/bak/Readme.txt b/root/programs/bak/Readme.txt new file mode 100644 index 000000000..ad01c458e --- /dev/null +++ b/root/programs/bak/Readme.txt @@ -0,0 +1 @@ +もともと programs 直下に置いていたものが、エージェンティックなリリースワークの新設で二軍落ち。 \ No newline at end of file