PowerShellでEdgeを自動化(インストール不要。参考:郵便追跡サービス自動操作)

1.経緯について


 RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。
※いざというときの手札として持っているだけで安心感が段違い

 見た目上IEがインストールされていなくても、CreateObjectをしたときにIEを呼び出すことができている状態ではあるが、Edgeでないと動かないようなシステムが出てきた場合のためにWebDriverなどのソフトをインストールせずにPowerShellといくつかのファイルをダウンロードするだけで自動化できる手段を探したところ、qiita.comにいくつか紹介がされているものがあった。
 試してみたところエラーに次ぐエラーですぐに試すことができなかったので備忘録として記録をしておく。
 サンプルとして郵便追跡サービスを自動操作しCSVをダウンロードするソースコードを載せてありますが、あくまで検証用です。サーバーに負荷をかけるような処理はしないでください。
 ※なお今時であればMicrosoftで無料のPowerautomateがあるので、それを使えばもっと安定かつノーコードで行けるのでいいと思いますが・・・。

2.はまったところ


  ・はまったポイント1

    ダウンロードしたdllを「LoadFile("WebDriver.dll")」で読み込んだらエラーが発生。
    エラーメッセージの一部:"ネットワーク上の場所からアセンブリを読み込もうとしました。これにより~~"

     → ネットからダウンロードしたdllはセキュリティ上そのままは使えない、らしい。
       dllを右クリックしてプロパティを修正することで回避する
     

  ・はまったポイント2

    「Newtonsoft.Jsonの依存関係がどうとか」いうエラーが発生し、「EdgeDriver」のインスタンス化でエラーが発生。
    色々調べたところWebDriver.dllをダウンロードしたときに最新のものを取ってきすぎてバージョンが対応していなかった。
          https://www.nuget.org/packages/Selenium.WebDriver/
     最新のdllをダウンロードすればいいと安直に思って、4.22.0を「Download pakage」を押下し、ダウンロードして、「selenium.webdriver.4.22.0.nupkg」の拡張子「nupkg」を「zip」に変更し、「lib\netstandard2.0\WebDriver.dll」を取り出して、使おうとしていた。


   ちゃんと見ると、青背景で「.NET Standard 2.0」と記載がされてる。


     → サイトが表示されたら過去のものを手に入れるため「Full status」をクリックする。


        「4.21.0」から順に開いていったが欲しいフレームワークのものがなかったので、「Show more」をクリックする


       ひたすら順番に見ていくと、「4.12.3」でほしいフレームワークのものがあった。


       すかさず、「Download pakage」をクリックして、中身から「WebDriver.dll」を取り出す。
  
       ※上述の「はまったポイント1」で対応をしたプロパティ設定の「セキュリティ」の設定変更を忘れないように!

  ・はまったポイント3

    要素が表示されるまでの待機を入れるために「WaitDriverWait」(WebDriverSupport.dll)を入れて、「ExpectedConditions」クラスを指定しようとしたら全然できなかった。
    → いろいろと調べていくともう廃止されている。「$edgeDriver.Manage().Timeouts().ImplicitWait = (New-TimeSpan -Seconds 10)」とすることで要素が取得するまで待ってくれる、らしい。

3.最終的な手順

  1)自分の環境に応じたバージョンのWebDriver.dllをダウンロードする

            https://www.nuget.org/packages/Selenium.WebDriver/
      ※自分の環境で作業した時点だと「4.12.3」の「lib\net48\WebDriver.dll」で動いた。人によっては環境が異なるので、頑張って試していただければと思います。

  2)ダウンロードしたWebDriver.dllを右クリック→プロパティを表示し、上述の「セキュリティ」を「許可する」に設定する


  3)EdgeのWebDriver(msedgedriver.exe)をダウンロードする

    https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/?form=MA13LH&ch=1


  4)デスクトップ等にフォルダを作成し、「Main.ps1」「WebDriver.dll」「msedgedriver.exe」を保存する


  5)Main.ps1に下記のソースを貼り付ける

   
   例)郵便の追跡番号を自動で設定しCSVファイルをダウンロードする

# --------------- Parameter Start

#  ◆ ファイルのダウンロードを待機する設定値
$INT_MAX_LOOP_COUNT_FOR_RETRY_DOWNLOAD_CHECK = 60; # 最大60回まで繰り返す
$INT_SLEEP_SECONDS_FOR_RETRY_DOWNLOAD_CHECK  = 1;  # リトライするまでの待機時間
#    ファイルのダウンロードが終わっているかどうかをチェックする際の待機時間と最大チェック回数。
#    待機時間×最大チェック回数の時間以内にダウンロードが終わらないと処理がエラーで終了する

$STR_DOWNLOAD_DIRECTORY = "C:\Users\ユーザー名\Downloads\DriverFolder";

# --------------- Parameter End ファイルのダウンロードを待機する設定値

# dllのロード
$strCurrentDir  = Split-Path $MyInvocation.MyCommand.path;

$webDriverDllPath = $strCurrentDir + "\WebDriver.dll";
$edgeDriverDirPath = $strCurrentDir + "\";

$asm = [System.Reflection.Assembly]::LoadFile($webDriverDllPath)


# ダウンロードフォルダが存在しない場合はフォルダを作成する
If(!(test-path $STR_DOWNLOAD_DIRECTORY)) { New-Item -ItemType Directory -Force -Path $STR_DOWNLOAD_DIRECTORY; }

# ◆ Edgeのオプションを生成
$Options = New-Object OpenQA.Selenium.Edge.EdgeOptions

##  ダウンロードフォルダを指定し、ダウンロードプロンプトが表示されないようにする。
##   https://stackoverflow.com/questions/35446893/c-sharp-set-default-download-directory-chrome-webdriver
$Options.AddUserProfilePreference("download.default_directory", $STR_DOWNLOAD_DIRECTORY);
$Options.AddUserProfilePreference("download.prompt_for_download", $false);
$Options.AddUserProfilePreference("disable-popup-blocking", "true");

##  拡張機能の自動更新を停止
$Options.AddArgument("useAutomationExtention=false")
##  「Edgeは自動テストソフトウェアによって制御されています」を非表示にする
$Options.AddExcludedArgument("enable-automation")
## ウィンドウサイズを最大にする
$Options.AddArgument("--start-maximized")

## EdgeDriverを生成する
$edgeDriver = New-Object OpenQA.Selenium.Edge.EdgeDriver($edgeDriverDirPath , $Options)

## Manage().Timeouts().ImplicitWaitを一度設定しておけば以降の
## FindElementやFindElementsで要素を取得するときに、毎回待機が行われるようになります。
## この処理が追加されたためWebDriverWaitを呼び出すときのExpectedConditionsクラスが廃止されている
$edgeDriver.Manage().Timeouts().ImplicitWait = (New-TimeSpan -Seconds 10)

# ◆ 郵便番号検索画面を操作する
##     郵便番号個別検索のケース
#$edgeDriver.Url = "https://trackings.post.japanpost.jp/services/srv/search/input"
#$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("requestNo1"))
#$x.SendKeys("123456789012")
## クリック
#$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("search"))
#$x.Click();

## 郵便番号連続のケース(最大100件ずつ検索ができる)
$edgeDriver.Url = "https://trackings.post.japanpost.jp/services/srv/sequenceNoSearch/input"

$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("requestNo"))
$x.SendKeys("123456789012") ## 調べたい番号の開始

$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("count"))
$x.SendKeys("1")

$x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Name("sequenceNoSearch"))
$x.Click();

## Edgeの開発者ツールでCSVダウンロードボタンを見たところ、ダウンロード用のサブウィンドウを呼び出すJavaScriptを実行していることがわかったため、JavaScriptを呼び出す
$edgeDriver.ExecuteScript("openSubWindowForPost('openSequenceNoSearchCsvCreate', 'sequenceNoSearchCsv', 540, 380)");

# ◆ CSVダウンロード画面を操作する
## CSVをダウンロードするためのサブ画面が呼び出されるのでWebDriverで操作する画面を切り替える必要がある
$CurrentWindowHandle = $edgeDriver.CurrentWindowHandle; # 現在のウィンドウハンドルの番号を退避
$WindowHandles = $edgeDriver.WindowHandles;             # WebDriverが操作できるすべてのウィンドウハンドルを取得する

## ダウンロード前のファイル名を退避
$arrFileitemsBefore = Get-ChildItem $STR_DOWNLOAD_DIRECTORY -File
$intFileCount = 0;
if( $arrFileitemsBefore -eq $null){ $intFileCount = 0;}
elseif ( $arrFileitemsBefore -is [array]){ $intFileCount = $arrFileitemsBefore.Length; }
else { $intFileCount = 1; }

## ダウンロード画面にDriverの操作画面を切り替えて、ダウンロードボタンを押下する
foreach ($handle in $WindowHandles){
    if ($edgeDriver.SwitchTo().Window($handle).Title -like "*CSVダウンロード*"){
        # ダウンロードボタンが取得できるまで繰り返すようにする
        #  このサイトの場合は、「CSVファイル作成を完了しました。」という文字が取れるまで待機してもよい課と思われる
        $x = $edgeDriver.FindElement([OpenQA.Selenium.By]::Id("download"))
        $x.Click();
        break;
    }
}

## 現在のファイル名を取得して比較して、存在しないファイル名があればダウンロードしたファイルと判断する
$strNewFileName = "";
$intLoopCount = 1 ;
$blnCompleteDonload = $false;

# ダウンロードが完了するまで待機する
# EdgeやChromeの場合、ダウンロード中かどうかは拡張子が「.crdownload」というファイルが作成されるので拡張子が変わるまで待機する
# ただしタイムアウトとして最大待ち時間は設定する
do {
    # ダウンロード処理・待機時間後のファイル名を退避
    $arrFileitemsAfter = Get-ChildItem $STR_DOWNLOAD_DIRECTORY -File

    foreach($item in $arrFileitemsAfter){
        $result = $arrFileitemsBefore | Where-Object Name -eq $item.Name ;
        if($result -eq $null){
            $strNewFileName = $item.Name;
            if ($item.Extension -ne ".crdownload") {
                $blnCompleteDonload = $true;
                Write-Host("ダウンロード完了。ファイル名:" + $item.Name)
            }
            break;
        }
    }
    $intLoopCount += 1;
    if( $blnCompleteDonload -eq $true ){ break; }
    else{ Start-Sleep -Seconds $INT_SLEEP_SECONDS_FOR_RETRY_DOWNLOAD_CHECK; }

} while ($intLoopCount -le $INT_MAX_LOOP_COUNT_FOR_RETRY_DOWNLOAD_CHECK)

# ダウンロードが終了したため、オブジェクトの終了をする
$edgeDriver.quit();

Exit;








PowerShellでsqlite3のパラメータクエリを発行

PowerShellでsqlite3を利用する記事を書いたが、SQLインジェクション対策を一切していなかった。PowerShellで作成するものの用途的に特にいらないかなと思っていたが、このご時世に対策できていないのもかっこ悪いのでSQLパラメータを利用するパターンのものを作成した。



#######################################################
# パラメータ変数格納用のクラス(SQLiteParameterだとインテリセンスやコードが長くなるため独自のクラスを作成)
#######################################################
Class clsSqlParameter {
    [string]$ParameterName;
    [object]$Value;

    # コンストラクタ
    clsSqlParameter(){

    }

    # コンストラクタ
    clsSqlParameter([string]$_ParameterName,[object]$_Value){
        $this.ParameterName = $_ParameterName;
        $this.Value = $_Value;
    }
}
   

    ############################################################
    # SQLを実行しデータを取得する。戻り値はDataTable
    # パラメータ変数を利用するので、System.Collections.Generic.List[clsSqlParameter]クラスのインスタンスを指定
    # <例>
    #  $lstParameters  = New-Object "System.Collections.Generic.List[clsSqlParameter]";
    #  $para = New-Object "clsSqlParameter" -ArgumentList "@para1", "060  ";
    #  #$para.ParameterName = "@para1";
    #  #$para.Value = "060  ";
    #  $lstParameters.Add($para);
    #   $dtResult = $dba.GetDataPara("SELECT * FROM KEN_ALL WHERE 郵便番号_5桁 = @para1 ",$lstParameters)
    ############################################################
    [System.Data.DataTable]GetDataPara([string]$strSQL,$lstParas){
        # エラーが発生した際に後続の処理を停止
        $ErrorActionPreference = "Stop"

        $sqlcmd = $null;
        $sqliteConnection = $null;
        $dataTable = $null;

        try {

            # SQLiteへの接続およびSQLステートメント発行用のSystem.Data.SQLite.SQLiteCommandの生成
            $sqliteConnection = New-Object System.Data.SQLite.SQLiteConnection;
           
            # .NETのライブラリのSQLiteは共有ファイルのデータベースへアクセスする場合、「\\SV-FOLDER\DataBase\Sample.sqlite3」のようなパスを指定したときに正常に接続できない
            # この場合は、「\\\\SV-FOLDER\DataBase\Sample.sqlite3」とする必要があることがわかったため修正
            $strConnectionString = "";
            if ($this.fstrDBFilePath.ToString().Substring(0,4) -ne "\\\\" -and $this.fstrDBFilePath.ToString().Substring(0,2) -eq "\\") {
                $strConnectionString = "Data Source = \\" + $this.fstrDBFilePath;
            } else {
                $strConnectionString = "Data Source = " + $this.fstrDBFilePath;
            }

            $sqliteConnection.ConnectionString = $strConnectionString ;
            $sqlcmd = New-Object System.Data.SQLite.SQLiteCommand;
            $sqlcmd.Connection = $sqliteConnection;
            $sqliteConnection.Open();

            # SELECT実行
            $sqlcmd.CommandText = $strSQL;
            foreach ($para in $lstParas) {
                $sqlitePara = New-Object "System.Data.SQLite.SQLiteParameter" -ArgumentList $para.ParameterName, $para.Value;
                $sqlcmd.Parameters.Add($sqlitePara);
            }
            $rs =  $sqlcmd.ExecuteReader();
           
            # Datatableにデータを取り込む
            $dataTable = New-Object System.Data.DataTable;
            $dataTable.Load($rs);
            $dataTable | Format-Table ;

        } catch {
            Write-Host "【エラー発生】GetDataPara";
            Write-Host ("エラーメッセージ:" + $_.Exception.Message);
            Write-Host ("クエリ:" + $strSQL);
        } finally {
            # SQLiteの切断
            $sqlcmd.Dispose()
            $sqliteConnection.Close()
        }
        return $dataTable;
    }

 

Visual Studio Codeの設定(PowerShellデバッグ)

1.外部ファイルの変更が反映されない

 PowerShellでWindowsフォームを作ることが多くなってきたので下記のような感じで、クラスごとにファイルを分けたり、共通関数をファイルにまとめたりしていたが、VSCodeでデバッグをしているときに外部ファイルで編集した内容が反映されないことがあって困っていた。Windows PowerShell ISEでも同じ発生し、毎回面倒だなと思いながら、エディタの再起動で頑張っていた。

 いろいろとネットを見ているとVSCodeに入れているPowerShellのデバッグ用の拡張機能の設定を変えることで、対応できることが分かったため備忘録として記載しておく。
VSCodeは「PowerShell Integrated Console」でスクリプトが実行されているらしく、拡張機能の設定の初期値が使いまわす設定になっている。
 これのおかげで、一度スクリプトを実行し、変数をインスタンス化して設定しておくことでほかのスクリプトで実行しても変数やAdd-Typeが適用されるというメリット?もあったデバッグの方法を変えるだけで対応できるので、下記のように変更を行うことにする

 ・変更前

 ・変更後("Create Temporary Integrated Console"のチェックボックスを入れる)


こうすることで、外部ファイルを編集したときに内容が反映されるようになる。

2.複数ファイルに分割したときのデバッグ

 Visual StudioでWindowsフォームを作るようにPowerShellでWindowsフォームのプロジェクトを作りたいと思っていろいろと頑張っていた。その際にVSCodeでデバッグするときの設定で初期設定では開いているファイルをデバッグするようになっており、複数画面を構成するときに1クラス1ファイルの構成で画面を作っていると毎回選択するファイルを変更することがめんどくさい・・・。

 【プロジェクトの構成】
   ・外部ファイルをインクルードする処理を記載した「Main.ps1」を最初に読み込み、「Main.ps1」の中で共通で使うクラスなどをインスタンス化し、「Script:clsCom」などのように呼び出す。
        ◆ Main.ps1

   ・各ファイルでは「$frm = New-Object "clsfrm*****"」のように指定して呼び出すことで、フォームのインスタンス化を行う

   ・デバッグするときにMain.ps1を選択してからデバッグを開始する必要がある

 解決策としていろいろとみていたが、VSCodeにある「デバッグの構成」でどのファイルからデバッグを行うのかを設定することがわかったので、設定を追加した。
 


構成を追加したことで、選択肢が増えているので、増えた選択肢を選んでF5でデバッグを行う

コンソールを確認すると「oject\Source>
PS C:\***\****\Source> . 'C:\***\****\Source\Main.ps1'」となっており、Main.ps1が実行されていることがわかる。

Main.ps1をエントリーポイントに指定することができるため、外部ファイルのインクルードやシステム全体で利用する変数の初期化、インスタンス化などを行うことができる。
外部ファイル側で呼び出すときは「Script」スコープで呼び出すことで利用することができる。
















PowerShellで別ファイルのクラスを読み込む(入れ子対応)

1.PowerShellで別ファイルのクラスを読み込む

 PowerShellで別ファイルに分割したクラスを読み込むときに「入れ子」が発生し、うまくいかないことがあった。

 Form1とForm2を作成し、お互いがお互いを参照しあうような場合に同じファイルを読み込んでしまいエラーが発生する。
 いろいろとネットを調べてみたけど解決策を見つけることができなかった。そもそもPowerShellで複数画面のWindowsフォームの開発をするのが間違っている気もするが、環境的にVSが入れれないので仕方なくいろいろと試してみた。

Form1.ps1
********************
$IncludeFile = Join-Path $PSScriptRoot "frm020_0000.ps1"
. $IncludeFile

# -----------------------------------------------------------------------
#  メイン画面を作成
# -----------------------------------------------------------------------
Class clsfrm010_0000 :System.Windows.Forms.Form {
    $lblTitle=[Label]@{
        Location = [Point]::new(5,5);
        Size=[Size]::new(250,20);
        Text = “タイトル”; 
    }

    #   ▼画面2を表示
    $btnOpenFrm02_0000=[Button]@{
        Location = [Point]::new(5,25);
        Size=[Size]::new(150,25);
        Text = "画面2を表示";
    }

    # コンストラクタ
    clsfrm010_0000 (){
        $this.Initialize();
    }
    
   # ------------------------------------------------------------------
    # 初期化処理
    # ------------------------------------------------------------------
    Initialize() {
        $this.Text = "画面1"
        $this.Size = [Size]::new(950, 720);
        $this.Font = New-Object Drawing.Font("MS Gothic",10) ;
        
        $this.Controls.Add($this.lblTitle);
        $this.Controls.Add($this.btnOpenFrm02_0000);
        # 作業開始遅延一覧
        $btnOpenFrm02_0000_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            $frmSearch = [clsfrm020_0000]::new();
            #$frmSearch = New-Object "clsfrm020_0000";
            $frmSearch.frmProject = $form;
            $frmSearch.Show();
        }
        $this.btnOpenFrm02_0000.add_Click($btnOpenFrm02_0000_Click);
    }
}


Form2.ps1
********************
$IncludeFile = Join-Path $PSScriptRoot "frm010_0000.ps1"
. $IncludeFile
# ------------------------------------------------------------------
#  メイン画面を作成
# ------------------------------------------------------------------
Class clsfrm020_0000 :System.Windows.Forms.Form {
    $lblTitle=[Label]@{
        Location = [Point]::new(5,5);
        Size=[Size]::new(250,20);
        Text = “タイトル”; 
    }

    #   ▼画面1を表示
    $btnOpenFrm01_0000=[Button]@{
        Location = [Point]::new(5,25);
        Size=[Size]::new(150,25);
        Text = "画面1を表示";
    }

    # コンストラクタ
    clsfrm020_0000 (){
        $this.Initialize();
    }
    
    # ------------------------------------------------------------------
    # 初期化処理
    # ------------------------------------------------------------------
    Initialize() {
        $this.Text = "画面2"
        $this.Size = [Size]::new(950, 720);
        $this.Font = New-Object Drawing.Font("MS Gothic",10) ;
        
        $this.Controls.Add($this.lblTitle);
        $this.Controls.Add($this.btnOpenFrm01_0000);
        # 作業開始遅延一覧
        $btnOpenFrm01_0000_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            $frmSearch = [clsfrm010_0000]::new();
            #$frmSearch = New-Object "clsfrm010_0000";
            $frmSearch.frmProject = $form;
            $frmSearch.Show();
        }
        $this.btnOpenFrm01_0000.add_Click($btnOpenFrm01_0000_Click);
    }
}

2.対応方法

標準モジュールにしてみたり、継承してうまくできないかいろいろと試したが、一番シンプルな対応方法は、以下のようにすることだった

 2-1.Form1.psとForm2.psの内容を書き換え

  $frmSearch = [clsfrm010_0000]::new();

     ↓

    $frmSearch = New-Object "clsfrm010_0000";


  $frmSearch = [clsfrm020_0000]::new();

     ↓

    $frmSearch = New-Object "clsfrm020_0000";

 2-2.Main.ps1を作ってそこから呼び出す


Main1.ps

******************************
using namespace System.Windows.Forms;
using namespace System.Drawing;

#デバッグ する際にはターミナルで流しておく必要がある。Classの継承を行っており、Class定義がスクリプトの中で一番最初に読み込まれる(?)ためエラーが出る。先に別ファイルやターミナルで実行することで回避

Add-Type -AssemblyName System.Windows.Forms;
Add-Type -AssemblyName System.Drawing;
# ISE上でデバッグするときには実行 →  Set-ExecutionPolicy RemoteSigned -Scope Process

# インクルードファイル
$IncludeFile = Join-Path $PSScriptRoot "Form1.ps1"
. $IncludeFile

$IncludeFile = Join-Path $PSScriptRoot "Form2.ps1"
. $IncludeFile

$frm = New-Object "clsfrm010_0000";
$frm.ShowDialog();

*****************

PowerShellでタスク管理ツールを作成(Ver0.9)

1. PowerShellでタスク管理

前回から作っていたPowerShellでWindowsFormを利用して作ったタスク管理ツールについて、ようやく作りたかった機能が大体盛り込むことができた。



データ構造としては1タスク=1フォルダ(タスクの内容はTask.xml)の構成とした。
データ件数が増えると処理速度が不安だけど100タスク(フォルダ・ファイル)ぐらいなら大丈夫と思う。
タスクが増えてくれば「アーカイブ」処理をすることで複数のタスクをZipファイルに圧縮して、とりまとめファイルを作ることで処理高速化ができるはず。

2.残作業

作ることを優先したので細かい日付変換処理やエラーチェック、などが全然放り込めていない。使いながら徐々にそのあたりは修正していこうと思う。

3.ソースコード


Main.ps1
--------------------------------------------------------------------------------------
Add-Type -AssemblyName System.Drawing;
Add-Type -AssemblyName System.Windows.Forms;

$CurrentDir  = Split-Path $MyInvocation.MyCommand.path;
$ScriptName = $MyInvocation.MyCommand.path;
$Basename    = $MyInvocation.MyCommand.Name;

#   データベースアクセス
$MenuFile = $CurrentDir + "\frm010_000_Project.ps1"; 
.$MenuFile;

[Application]::EnableVisualStyles();
$form = [frm010_000_Projet]::new();
$form.fstrCurrentPath = $CurrentDir;
$form.StartPosition="CenterScreen";   # 列挙体は文字列で指定する必要がある
$form.ShowDialog();

frm010_000_Project.ps1
--------------------------------------------------------------------------------------
using namespace System.Windows.Forms;
using namespace System.Drawing;

#デバッグ する際にはターミナルで流しておく必要がある。Classの継承を行っており、Class定義がスクリプトの中で一番最初に読み込まれる(?)ためエラーが出る。先に別ファイルやターミナルで実行することで回避

Add-Type -AssemblyName System.Windows.Forms;
Add-Type -AssemblyName System.Drawing;
# ISE上でデバッグするときには実行 →  Set-ExecutionPolicy RemoteSigned -Scope Process

# [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
# [void][reflection.assembly]::LoadWithPartialName("System.Drawing")

# 定数宣言
[string]$CONST_SAMPLE = "SAMPLE";
[string]$DATA_FILE_NAME = "Task.xml";
[string]$DATA_ARCHIVE_FILE_NAME = "TaskArchive_";  # TaskArchive_[ID].xml ファイル名の順番で並ばせる必要があるためTask.xmlの後に並ぶように名前に気を付ける
[string]$DATA_TABLE_NAME_CONTENT = "ContentsData";
[string]$DATA_TABLE_NAME_HISTORY = "HistoryData";

[string]$COLNAME_CONTENTS_ID = "ID";
[string]$COLNAME_CONTENTS_TITLE = "Title";
[string]$COLNAME_CONTENTS_LIMITDAY = "LimitDay";
[string]$COLNAME_CONTENTS_LIMITALERTDAYCOUNT = "LimitAlertDayCount";
[string]$COLNAME_CONTENTS_STATUS = "Status";
[string]$COLNAME_CONTENTS_COLORLABEL = "ColorLabel";
[string]$COLNAME_CONTENTS_MEMBER = "Member";
[string]$COLNAME_CONTENTS_CLASS = "Class";
[string]$COLNAME_CONTENTS_CREATEIONDATETIME = "CreateDateTime";
[string]$COLNAME_CONTENTS_CONTENTS = "Contents";
[string]$COLNAME_CONTENTS_NOTE = "Note";
[string]$COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH = "RelativePath";
[string]$COLNAME_CONTENTS_FILEPATH = "FilePath";

[string]$COLNAME_HISTORY_ID = "ID";
[string]$COLNAME_HISTORY_HISTORYID = "HistoryID";
[string]$COLNAME_HISTORY_PATTERN = "Pattern";
[string]$COLNAME_HISTORY_CONTROL = "Control";
[string]$COLNAME_HISTORY_CREATEIONDATETIME = "CreateDateTime";
[string]$COLNAME_HISTORY_USERNAME = "UserName";
[string]$COLNAME_HISTORY_HISTORYCONTENTS = "HistoryContents";

[string]$COLNAME_CONTENTS_FOR_FREESEARCH = "FreeSearch";
[string]$COLNAME_CONTENTS_FOR_COMMENTSSEARCH = "CommentSearch";
[string]$COLNAME_CONTENTS_FOR_FILEPATTERN = "FilePattern";
[string]$COLNAME_CONTENTS_FOR_SORT = "Sort";
[string]$COLNAME_CONTENTS_FOR_SORTSUB = "SortSub";

[string]$DGV_COLNAME_ID = "colID";
[string]$DGV_COLNAME_HISTORY_ID = "colHistoryID";
[string]$DGV_COLNAME_TRKDATETIME = "colTrkDateTime";
[string]$DGV_COLNAME_KBN = "colKbn";
[string]$DGV_COLNAME_CONTROL = "colControl";
[string]$DGV_COLNAME_HOSTNAME = "colHostName";
[string]$DGV_COLNAME_CONTENTS = "colContents";

[string]$DGV_COLNAME_CONTENTS_ID = "colId";
[string]$DGV_COLNAME_CONTENTS_FILEPATTERN = "FilePattern";
[string]$DGV_COLNAME_CONTENTS_COLOR = "colColor";
[string]$DGV_COLNAME_CONTENTS_TITLE = "colTitle";
[string]$DGV_COLNAME_CONTENTS_LIMITDAY = "colLimitDay";
[string]$DGV_COLNAME_CONTENTS_LIMITALERTDAYCOUNT = "colLimitAlertDayCount";
[string]$DGV_COLNAME_CONTENTS_STATUS = "colStatus";
[string]$DGV_COLNAME_CONTENTS_COLORLABEL = "colColorLabel";
[string]$DGV_COLNAME_CONTENTS_MEMBER = "colMember";
[string]$DGV_COLNAME_CONTENTS_CLASS = "colClass";
[string]$DGV_COLNAME_CONTENTS_CREATEIONDATETIME = "colCreateDateTime";
[string]$DGV_COLNAME_CONTENTS_CONTENTS = "colContents";
[string]$DGV_COLNAME_CONTENTS_NOTE = "colNote";
[string]$DGV_COLNAME_CONTENTS_FILEPATH = "colFilePath";

[string]$DGV_HISTORY_COLNAME_ID = "colId";
[string]$DGV_HISTORY_COLNAME_HISTORYID = "colHistoryId";
[string]$DGV_HISTORY_COLNAME_TRKDATETIME = "colTrkDateTime";
[string]$DGV_HISTORY_COLNAME_KBN = "colKbn";
[string]$DGV_HISTORY_COLNAME_CONTROL = "colControl";
[string]$DGV_HISTORY_COLNAME_HOSTNAME = "colHostName";
[string]$DGV_HISTORY_COLNAME_CONTENTS = "colContents";

[string]$DGV_ALIGN_MIDDLECENTER = "MiddleCenter";
[string]$DGV_ALIGN_MIDDLELEFT = "MiddleLeft";
[string]$DGV_ALIGN_MIDDLERIGHT = "MiddleRight";

[string]$FILEPATTERN_TASK = "";
[string]$FILEPATTERN_ARCHIVE = "アーカイブ";

[string]$STATUS_TODO = "作業前";
[string]$STATUS_DOING = "作業中";
[string]$STATUS_DONE = "作業完了";

[string]$PATTERN_AUTO = "自動";
[string]$PATTERN_CHANGELOG = "変更";
[string]$PATTERN_COMMENT = "コメント";

[string]$LABELCOLOR_RED = "赤";
[string]$LABELCOLOR_PINK = "桃";
[string]$LABELCOLOR_PURPLE = "紫";
[string]$LABELCOLOR_ORANGE = "橙";
[string]$LABELCOLOR_YELLOW = "黄";
[string]$LABELCOLOR_GREEN = "緑";
[string]$LABELCOLOR_LIGHTBLUE = "水";
[string]$LABELCOLOR_BLUE = "青";

$CurrentDir  = Split-Path $MyInvocation.MyCommand.path;
$ScriptName = $MyInvocation.MyCommand.path;
$Basename    = $MyInvocation.MyCommand.Name;

# ------------------------------------------------------------------------------------------------------------
#  メイン画面を作成
# ------------------------------------------------------------------------------------------------------------
Class frm010_000_Projet :System.Windows.Forms.Form{
    
    #region Class 変数
    [string]$fstrCurrentPath; # インスタンス後に設定される。$MyInvocation.MyCommandはスクリプト内で定義されており、ウォッチ式は見れるがクラスの中では取得できない。
    [System.Collections.Generic.Dictionary[string,TreeNode]]$fdicNodes;
    [System.Collections.Generic.Dictionary[string,TreeNode]]$fdicNodesById;
    [System.Data.DataSet]$fdsCurrentData ;
    #endregion

    #region Design 
    # ↓↓↓↓↓  Design Start
    # 色:https://www.lab-nemoto.jp/www/leaflet_edu/else/ColorMaker.html
    #   ▼タイトル
    $lblTitle=[Label]@{
        Location = [Point]::new(5,5);
        Size=[Size]::new(80,20);
        Text = “タイトル”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $txtTitle=[TextBox]@{
        Location = [Point]::new(88,5);
        Size=[Size]::new(20,20);
        Anchor="Top,Left,Right";
        Text = “”;
    }

    #   ▼期限
    $lblLimit=[Label]@{
        Location = [Point]::new(5,30);
        Size=[Size]::new(80,20);
        Text = “期限”;  
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtLimit=[TextBox]@{
        Location = [Point]::new(88,30);
        Size=[Size]::new(90,30);
        Anchor="Top,Left";
        Text = “”;
    }

    #   ▼期限通知カウント
    $txtAlertDayCount=[TextBox]@{
        Location = [Point]::new(180,30);
        Size=[Size]::new(20,30);
        Anchor="Top,Left";
        TextAlign = [System.Windows.Forms.HorizontalAlignment]::Right;
        MaxLength = 1;
        Text = “”;
    }
    $lblAlertDayCount=[Label]@{
        Location = [Point]::new(202,32);
        Size=[Size]::new(85,20);
        Text = “日前に通知”;        
        Anchor="Top,Left";
        BorderStyle="None";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    
    #   ▼進捗状況
    $lblStatus=[Label]@{
        Location = [Point]::new(290,30);
        Size=[Size]::new(75,20);
        Text = “進捗状況”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $cboStatus=[ComboBox]@{
        Location = [Point]::new(368,30);
        Size=[Size]::new(90,20);
        DropDownStyle = "DropDownList";
    }

    #   ▼色
    $lblColorLabel=[Label]@{
        Location = [Point]::new(465,30);
        Size=[Size]::new(50,20);
        Text = “色”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $cboColorLabel=[ComboBox]@{
        Location = [Point]::new(517,30);
        Size=[Size]::new(45,20);
        DropDownStyle = "DropDownList";
    }
    $lblStickyNote=[Label]@{
        Location = [Point]::new(565,30);
        Size=[Size]::new(20,20);
        Text = “”;        
        #BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    #   ▼担当
    $lblMember=[Label]@{
        Location = [Point]::new(5,55);
        Size=[Size]::new(80,20);
        Text = “担当”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtMember=[TextBox]@{
        Location = [Point]::new(88,55);
        Size=[Size]::new(115,30);
        Anchor="Top,Left";
        Text = “”;
    }

    #   ▼分類
    $lblClass=[Label]@{
        Location = [Point]::new(212,55);
        Size=[Size]::new(60,20);
        Text = “分類”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtClass=[TextBox]@{
        Location = [Point]::new(275,55);
        Size=[Size]::new(90,30);
        Anchor="Top,Left";
        Text = “”;
    }

    #   ▼登録日時
    $lblCreateDateTime=[Label]@{
        Location = [Point]::new(367,55);
        Size=[Size]::new(65,20);
        Text = “登録日時”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtCreateDateTime=[TextBox]@{
        Location = [Point]::new(435,55);
        Size=[Size]::new(167,30);
        Anchor="Top,Left";
        Text = “”;
        ReadOnly = $True
    }

    #   ▼コンテンツ
    $lblContents=[Label]@{
        Location = [Point]::new(5,80);
        Size=[Size]::new(80,20);
        Text = “内容”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtContents=[TextBox]@{
        Location = [Point]::new(88,80);
        Size=[Size]::new(20,105);
        Anchor="Top,Left,Right";
        Text = “”;
        WordWrap = $True;
        ScrollBars = "Both";
        Multiline = $True;
    }

    #   ▼備考
    $lblNote=[Label]@{
        Location = [Point]::new(5,190);
        Size=[Size]::new(80,20);
        Text = “備考”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtNote=[TextBox]@{
        Location = [Point]::new(88,190);
        Size=[Size]::new(20,65);
        Anchor="Top,Left,Right";
        Text = “”;
        WordWrap = $True;
        ScrollBars = "Both";
        Multiline = $True;
    }

    #   ▼メインとなるテーブルレイアウトパネル
    $tlpMainLayout=[TableLayoutPanel]@{
        ColumnCount = 1;
        RowCount=2;
        Dock= "Fill";
    }

    #   ▼メインとなるテーブルレイアウトパネル
    $tlpCommentLayout=[TableLayoutPanel]@{
        ColumnCount = 3;
        RowCount=2;
        Dock= "Fill";
    }
    
    #   ▼変更履歴を表示するかどうかのチェックボックス
    $chkShowHistory=[CheckBox]@{
        Location = [Point]::new(5,2);
        Size=[Size]::new(140,20);
        Anchor="Top,Left";
        Text = "変更履歴を表示"
        Checked=$false;
    }

    #   ▼変更履歴及びコメント一覧
    $dgv = [DataGridView]@{
        Location = [Point]::new(5,23);
        Size=[Size]::new(140,20);
        Anchor="Top,Left,Right,Bottom";
        AutoGenerateColumns=$false;
        AllowUserToAddRows=$False;
        AllowUserToDeleteRows=$False;
        ReadOnly=$True;
    }

    #   ▼履歴内容
    $lblHistoryContents=[Label]@{
        Location = [Point]::new(5,5);
        Size=[Size]::new(290,20);
        Text = “履歴内容”;        
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        Dock="Fill";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtHistoryContents=[TextBox]@{
        Location = [Point]::new(5,28);
        Size=[Size]::new(290,10);
        Dock="Fill";
        Anchor="Top,Bottom,Left";
        Text = “”;
        WordWrap = $True;
        ScrollBars = "Both";
        ReadOnly=$true;
        Multiline = $True;
    }

    #   ▼コメント
    $lblComments=[Label]@{
        Location = [Point]::new(298,5);
        Size=[Size]::new(290,20);
        Text = “追加コメント”;        
        Dock="Fill";
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtComments=[TextBox]@{
        Location = [Point]::new(298,28);
        Size=[Size]::new(290,10);
        Anchor="Top,Bottom,Left";
        Text = "";
        Dock="Fill";
        WordWrap = $true;
        ScrollBars = "Both";
        Multiline = $True;
    }

    #   ▼追加ボタン
    $btnAddComment=[Button]@{
        Location = [Point]::new(5,70);
        Size=[Size]::new(50,25);
        BackColor = "LightGray";
        Anchor="Left,Bottom";
        Text = "追加";
    }

    #   ▼登録内容と履歴内容の区切り(TreeViewとその右側の区切り)
    $SpContainVertical=[SplitContainer]@{
        Dock="Fill";
        Orientation = "Vertical";
        BorderStyle = "FixedSingle"
    }

    #   ▼登録内容と履歴内容の区切り(タスク内容と履歴内容の水平区切り)
    $SpContainTask=[SplitContainer]@{
        Dock="Fill";
        Orientation = "Horizontal";
        BorderStyle = "FixedSingle";
        # Initializeでコントロールの追加をしてからでないとうまく反映できないためコメントアウト
        # SplitterDistance = 50; 
    }

    $SpContainHorizontal=[SplitContainer]@{
        Dock="Fill";
        Orientation = "Horizontal";
        BorderStyle = "FixedSingle";
    }

    #   ▼TreeView
    $tvTasks = [TreeView]@{
        Dock="Fill";
        AllowDrop = $True;
        HideSelection = $False; # フォーカスを失ってもノードの選択状態を維持する
    }

    #   ▼メニューバー
    $menuFormMain = [MenuStrip]@{

    }

    #   ▼DataGridView用のコンテキストメニュー
    $dgvContextMenu = [ContextMenuStrip]@{

    }
    # ↑↑↑↑↑ Design End
    #endregion

    #region ↓↓↓↓↓ Method

    # コンストラクタ
    frm010_000_Projet(){

        $this.Initialize();

        # Load_Events
        $frm_Load = {
            $this.RefreshTreeViewNodes();
            $this.SpContainTask.SplitterDistance = 260;
            $this.SpContainHorizontal.SplitterDistance = 150;
        }
        $this.add_Load($frm_Load);

    }  

    # ------------------------------------------------------------------------------------------------------------
    # 初期化処理
    # ------------------------------------------------------------------------------------------------------------
    Initialize() {
        $this.Text = "タスクツリー"
        $this.Size = [Size]::new(950, 670);
        $this.Font = New-Object Drawing.Font("MS Gothic",10) ;
        $this.dgv.Font = New-Object Drawing.Font("MS Gothic",9) ;
        $this.chkShowHistory.Font = New-Object Drawing.Font("MS Gothic",9) ;
        
        #$this.Font = New-Object Drawing.Font("BIZ UDGothic",10) ;
        #$this.dgv.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
        #$this.chkShowHistory.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
        
        $this.BackColor = [System.Drawing.Color]::FromArgb(232, 241, 255);

        $this.fdicNodes = [System.Collections.Generic.Dictionary[String, PSObject]]::new();
        $this.fdicNodesById = [System.Collections.Generic.Dictionary[String, PSObject]]::new();
        
        # ◆ コントロールを追加
        #   レイアウトロジックを停止する
        $this.SuspendLayout()
    
        #    Menuを追加する
        $this.MenuControlInit()

        #   各種パネルを追加する
        #      TableLayoutPanelを一番下に配置し、SplitContainerパネルを配置していく
        $this.Controls.Add($this.tlpMainLayout)
        $this.tlpMainLayout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle("Absolute",70)));  # 最低でもメニューバーの分は必要。検索用ボタンを配置予定。
        $this.tlpMainLayout.CellBorderStyle = "Single";
        $this.tlpMainLayout.Controls.Add($this.SpContainVertical,0,1);
        $this.SpContainVertical.Panel2.Controls.Add($this.SpContainTask);
        $this.SpContainTask.Panel2.Controls.Add($this.SpContainHorizontal);
    
        #   画面右側のタスクの登録項目を配置していく
        $this.SpContainTask.Panel1.Controls.Add($this.lblTitle);
        $this.SpContainTask.Panel1.Controls.Add($this.txtTitle);
        $this.SpContainTask.Panel1.Controls.Add($this.lblLimit);
        $this.SpContainTask.Panel1.Controls.Add($this.txtLimit);
        $this.SpContainTask.Panel1.Controls.Add($this.txtAlertDayCount);
        $this.SpContainTask.Panel1.Controls.Add($this.lblAlertDayCount);
        $this.SpContainTask.Panel1.Controls.Add($this.lblStatus);
        $this.SpContainTask.Panel1.Controls.Add($this.cboStatus);
        $this.SpContainTask.Panel1.Controls.Add($this.lblColorLabel);
        $this.SpContainTask.Panel1.Controls.Add($this.cboColorLabel);
        $this.SpContainTask.Panel1.Controls.Add($this.lblStickyNote);
        $this.SpContainTask.Panel1.Controls.Add($this.lblMember);
        $this.SpContainTask.Panel1.Controls.Add($this.txtMember);        
        $this.SpContainTask.Panel1.Controls.Add($this.lblClass);
        $this.SpContainTask.Panel1.Controls.Add($this.txtClass);
        $this.SpContainTask.Panel1.Controls.Add($this.lblCreateDateTime);
        $this.SpContainTask.Panel1.Controls.Add($this.txtCreateDateTime);
        $this.SpContainTask.Panel1.Controls.Add($this.lblContents);
        $this.SpContainTask.Panel1.Controls.Add($this.txtContents);
        $this.SpContainTask.Panel1.Controls.Add($this.lblNote);
        $this.SpContainTask.Panel1.Controls.Add($this.txtNote);

        #   履歴一覧を表示する
        $this.SpContainHorizontal.Panel1.Controls.Add($this.dgv);
        $this.SpContainHorizontal.Panel1.Controls.Add($this.chkShowHistory);

        #   選択された行のコメント内容や新規コメント追加用のコントロールを配置する
        $this.SpContainHorizontal.Panel2.Controls.Add($this.tlpCommentLayout)
        $this.tlpCommentLayout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle("Absolute",20)));
        $this.tlpCommentLayout.RowStyles.Add((New-Object System.Windows.Forms.RowStyle("AutoSize")));
        $this.tlpCommentLayout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle("Percent",50)));
        $this.tlpCommentLayout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle("Percent",50)));
        $this.tlpCommentLayout.ColumnStyles.Add((New-Object System.Windows.Forms.ColumnStyle("Absolute",60)));
        #$this.tlpCommentLayout.BackColor = "Yellow";        # Debug用
        #$this.tlpCommentLayout.CellBorderStyle = "Single";  # Debug用

        $this.tlpCommentLayout.Controls.Add($this.lblHistoryContents,0,0);
        $this.tlpCommentLayout.Controls.Add($this.txtHistoryContents,0,1);
        $this.tlpCommentLayout.Controls.Add($this.lblComments,1,0);
        $this.tlpCommentLayout.Controls.Add($this.txtComments,1,1);
        $this.tlpCommentLayout.Controls.Add($this.btnAddComment,2,1);
        
        #   タスクツリービューを追加する
        $this.SpContainVertical.Panel1.Controls.Add($this.tvTasks);

        # ◆ コンボボックスの選択肢を生成
        #   進捗状況コンボボックス
        $this.cboStatus.Items.Clear();
        $this.cboStatus.Items.Add($script:STATUS_TODO);
        $this.cboStatus.Items.Add($script:STATUS_DOING);
        $this.cboStatus.Items.Add($script:STATUS_DONE);
        #   色コンボボックス
        $this.cboColorLabel.Items.Clear();
        $this.cboColorLabel.Items.Add("");
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_RED);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_PINK);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_PURPLE);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_ORANGE);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_YELLOW);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_GREEN);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_LIGHTBLUE);
        $this.cboColorLabel.Items.Add($script:LABELCOLOR_BLUE);
                
        # ◆ 各種イベントを追加
        #   タイトル
        $txtTitle_Leave={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            # TreeView側のタイトルを更新し、ファイルを保存する
            $form.tvTasks.SelectedNode.Text = $form.txtTitle.Text;  
            $form.SaveFile($form.tvTasks.SelectedNode.Tag);
        }
        $this.txtTitle.add_Leave($txtTitle_Leave);

        #   期限
        $txtLimitDay_Leave={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            # 日付形式を変換し、TreeViewNodeを更新する
            $sender.Text = $form.GetDateTryConvertFromString($sender.Text); 
            $form._SetTreeNodeStyle($form.tvTasks.SelectedNode,$form.cboStatus.Text,$form.txtLimit.Text,$form.txtAlertDayCount.Text,$form.cboColorLabel.Text);
        }
        $this.txtLimit.add_Leave($txtLimitDay_Leave);

        #   期限通知日数
        $txtAlertDayCount_Leave = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            if ([double]::TryParse($sender.Text,[ref]$null) -ne $true){
                $sender.Text = "";
                [System.Windows.Forms.MessageBox]::Show("数値で入力してください", "エラー");
                $sender.Focus();
            } elseif ($sender.Text.Length -ne 1) {
                $sender.Text = "";
                [System.Windows.Forms.MessageBox]::Show("1桁で入力してください", "エラー");
                $sender.Focus();
            } else {
                $form._SetTreeNodeStyle($form.tvTasks.SelectedNode,$form.cboStatus.Text,$form.txtLimit.Text,$form.txtAlertDayCount.Text,$form.cboColorLabel.Text);
            }
        }
        $this.txtAlertDayCount.add_Leave($txtAlertDayCount_Leave);

        #   処理状況
        $cboStatus_Leave={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            # TreeViewのNodeのスタイルを更新し、表示してからデータを更新する
            $form._SetTreeNodeStyle($form.tvTasks.SelectedNode,$form.cboStatus.Text,$form.txtLimit.Text,$form.txtAlertDayCount.Text,$form.cboColorLabel.Text);
            $form.SaveFile($form.tvTasks.SelectedNode.Tag);
        }
        $this.cboStatus.add_Leave($cboStatus_Leave);

        #    カラーラベル
        $cboColorLabel_Leave={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            # 色確認用のラベルの色を変更し、TreeNodeの書式を変更する
            $form.SetStickyNoteColor($sender); 
            $form._SetTreeNodeStyle($form.tvTasks.SelectedNode,$form.cboStatus.Text,$form.txtLimit.Text,$form.txtAlertDayCount.Text,$form.cboColorLabel.Text);
        }
        $this.cboColorLabel.add_Leave($cboColorLabel_Leave);

        #   履歴表示チェックボックス
        $chkShowHistory_CheckedChange={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            $form.dgv.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
            foreach($dgvRow in $form.dgv.Rows){
                if ($dgvRow.Cells[$script:DGV_COLNAME_KBN].Value -eq $script:PATTERN_CHANGELOG) {$dgvRow.Visible=$form.chkShowHistory.Checked;}
            }
        }
        $this.chkShowHistory.add_CheckedChanged($chkShowHistory_CheckedChange);

        #     履歴一覧
        $dgv_CurrentCellChanged = {
            $sender = $args[0];
            $e = $args[1];
            $form =$sender.FindForm();
            if ( $form.dgv -eq $null) { return;}
            if ( $form.dgv.CurrentRow -eq $null) { return;}
            
            $form.txtHistoryContents.Text = $form.dgv.CurrentRow.Cells[$script:DGV_COLNAME_CONTENTS].Value;
        }
        $this.dgv.add_CurrentCellChanged($dgv_CurrentCellChanged);

        #「行削除」メニュー項目をDataGridViewの右クリックに作成する
        $dgvRowDelMenuItem = New-Object ToolStripMenuItem;
        $dgvRowDelMenuItem.Text = "行削除";
        $this.dgvContextMenu.Items.Add($dgvRowDelMenuItem);

        $dgvRowDelMenuItem_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.SourceControl.FindForm();
            if ( $form.dgv -eq $null) { return;}
            if ( $form.dgv.CurrentRow -eq $null) { return;}
            $form.DeleteRowIndgv();
        }
        $this.dgvContextMenu.add_Click($dgvRowDelMenuItem_Click);
        $this.dgv.ContextMenuStrip = $this.dgvContextMenu;

        # ◆ TreeView関連
        #    選択変更前に画面上の内容を保存する
        $TreeView_BeforeSelect ={
            $sender = $args[0];
            $e = $args[1];
            
            $CurrentSelectedNode = $sender.SelectedNode;
            if ($CurrentSelectedNode -ne $null){
                $thisForm = $sender.FindForm();
                $thisForm.SaveFile($CurrentSelectedNode.Tag);
                $CurrentSelectedNode.Text = $thisForm.GetTaskTitle($CurrentSelectedNode.Tag);
            }
        };
        $this.tvTasks.add_BeforeSelect($TreeView_BeforeSelect);
        
        #    選択された内容を画面上に表示する
        $TreeView_AfterSelect={
            $sender = $args[0];
            $e = $args[1];
            $sender.FindForm().SetDataFromFile($e.Node.Tag)
        };
        $this.tvTasks.add_AfterSelect($TreeView_AfterSelect);

        #    TreeViewのDragDrop処理
        $TreeView_ItemDrag = {
            $sender = $args[0];
            $e = $args[1];
            [TreeView]$tv = $sender;
            $tv.SelectedNode = $e.Item;
            $tv.Focus();
            # ノードのドラッグを開始する
            $dde = $tv.DoDragDrop($e.Item , [System.Windows.Forms.DragDropEffects]::All);
        };
        $TreeView_DragOver = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();

            #  ドラッグされているデータがTreeNodeか調べる
            if ($e.Data.GetDataPresent([TreeNode])){
                $e.Effect = [DragDropEffects]::Move;
            } else {
                # TreeNodeでなければ受け入れない
                $e.Effect = [DragDropEffects]::None;
            }

            # マウス下のNodeを選択する
            if ($e.Effect -ne [DragDropEffects]::None)
            {
                [TreeView] $tv = $sender;
                # マウスのあるNodeを取得する
                [TreeNode] $target = $tv.GetNodeAt($tv.PointToClient([Point]::new($e.X, $e.Y)));
                #ドラッグされているNodeを取得する
                [TreeNode] $source =$e.Data.GetData([TreeNode]);
                #マウス下のNodeがドロップ先として適切か調べる
                if (($target -ne $Null) -And ($target -ne $source) -And ($form.IsChildNode($source, $target) -ne $True))
                {
                    if ( $target.IsSelected -eq $false) {
                        $tv.SelectedNode = $target;
                    }
                }
                else {
                    $e.Effect = [DragDropEffects]::None;
                }
            }
        };
        $TreeView_DragDrop = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();

            if ($e.Data.GetDataPresent([TreeNode])){
                $e.Effect = [DragDropEffects]::Move;
                [TreeView] $tv = $sender;
                # ドロップされたデータ(TreeNode)を取得
                [TreeNode] $source = $e.Data.GetData([TreeNode]);
                # ドロップ先のTreeNodeを取得する
                [TreeNode] $target = $tv.GetNodeAt($tv.PointToClient([Point]::new($e.X, $e.Y)));
                # マウス下のNodeがドロップ先として適切か調べる
                if (($target -ne $Null) -And ($target -ne $source) -And ($form.IsChildNode($source, $target) -ne $True))
                {
                    $dicInfoSource = New-Object System.IO.DirectoryInfo($source.Tag);
                    $dicInfoTarget = New-Object System.IO.DirectoryInfo($target.Tag);

                    $strChangeLog = "";
                    $strChangeLog += $form.GetTaskTitle($dicInfoSource.Parent.FullName) + "`r`n";
                    $strChangeLog += "↓↓↓↓↓↓`r`n";
                    $strChangeLog += $form.GetTaskTitle($dicInfoTarget.FullName) + "`r`n";

                    $tv.SelectedNode = $source;
                    $form.OpenFile($dicInfoSource.Tag)

                    $strPathFrom = $dicInfoSource.FullName;
                    $strPathTo = $dicInfoTarget.FullName; 
                    $strId_To = $form.GetIdFromPath($strPathTo);
                    
                    # フォルダを移動
                    Move-Item $strPathFrom $strPathTo
                    
                    # 移動した履歴を登録する
                    $form._AddHistory("フォルダ移動" + "`r`n" + $strChangeLog,$false);
    
                    # TreeViewを再構築
                    $form.RefreshTreeViewNodes();

                    $target = $form.fdicNodesById[$strId_To];
                    $target.Expand();

                    #  追加されたNodeを選択
                    $tv.SelectedNode = $target;

                } else {$e.Effect = [DragDropEffects]::None;}

            } else {
                # TreeNodeでなければ受け入れない
                $e.Effect = [DragDropEffects]::None;
            }

        }
        $this.tvTasks.add_ItemDrag($TreeView_ItemDrag);
        $this.tvTasks.add_DragOver($TreeView_DragOver);
        $this.tvTasks.add_DragDrop($TreeView_DragDrop);

        # コメント追加ボタン
        $btnAddComment_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            $form._AddHistory($form.txtComments.Text,$False);
            $form.SaveFile($form.tvTasks.SelectedNode.Tag);
        }
        $this.btnAddComment.add_Click($btnAddComment_Click);

        # 画面上のキー押下処理
        $this.KeyPreview=$True;
        $KeyDownEvent={
                $sender = $args[0];
                $e = $args[1];
                $this.RunFunctionKeyDownEvents($sender,$e);
        }
        $this.add_KeyDown($KeyDownEvent);

        # DataGridViewを設定
        $this.DataGridViewInit();

        # レイアウトを再開
        $this.ResumeLayout();


    }
    
    # ------------------------------------------------------------------------------------------------------------
    # Function Key 押下時イベント
    # ------------------------------------------------------------------------------------------------------------
    RunFunctionKeyDownEvents([object] $sender, [KeyEventArgs] $e){
        $PushKeyCode= $e.KeyCode;
        
        $selectedTask = $this.tvTasks.SelectedNode;
        if (( $e.Control -eq $true) -And ( $e.KeyCode -eq ([System.Windows.Forms.Keys]::S)) ) {
            # 上書き保存し、Treeを再描画
            $this.SaveFile($selectedTask.Tag);
            $this.RefreshTreeViewNodes();
        }

        If ( $PushKeyCode -eq "F1" ) {
            # 下のレベルにタスクを追加
            if ($selectedTask -eq $null){ $this.AddTaskNode($this.GetDataFolderPath(), $false);}
            else {$this.AddTaskNode($selectedTask.Tag, $false);}

        } ElseIf ($PushKeyCode -eq "F2" ){
            # 同じレベルにタスクを追加
            if ($selectedTask -eq $null){ $this.AddTaskNode($this.GetDataFolderPath(), $false);}
            else {$this.AddTaskNode($selectedTask.Tag, $true);}
        } ElseIf ($PushKeyCode -eq "F3" ){
            # タスクを上へ移動
            if ($selectedTask -ne $null){ $this.MoveTask($selectedTask, $true);}
        } ElseIf ($PushKeyCode -eq "F4" ){
            # タスクを下へ移動
            if ($selectedTask -ne $null){ $this.MoveTask($selectedTask, $false);}
        } ElseIf ($PushKeyCode -eq "F5" ){
            # 再描画
            $this.RefreshTreeViewNodes();
        } ElseIf ($PushKeyCode -eq "F6" ){
            #$this.btnF06.PerformClick();
        } ElseIf ($PushKeyCode -eq "F7" ){
            #$this.btnF07.PerformClick();
        } ElseIf ($PushKeyCode -eq "F8" ){
            #$this.btnF08.PerformClick();
        } ElseIf ($PushKeyCode -eq "F9" ){
            #$this.btnF09.PerformClick();
        } ElseIf ($PushKeyCode -eq "F10" ){
            # [System.Windows.Forms.MessageBox]::Show("押されたキーは:${PushKeyCode}です", "結果")
            #$this.btnF10.PerformClick();
        } ElseIf ($PushKeyCode -eq "F11" ){
            #$this.btnF11.PerformClick();
        } ElseIf ($PushKeyCode -eq "F12" ){
            #$this.btnF12.PerformClick();
        }
    }

    
    # ------------------------------------------------------------------------------------------------------------
    # 渡された日付をyyyy/MM/dd形式に変換する
    # 変換できない場合は空白を返す
    # https://teratail.com/questions/118618
    # ------------------------------------------------------------------------------------------------------------
    [string]GetDateTryConvertFromString([string]$userInputDate){
        # 対応する入力パターン
        [string[]]$dateFormats = @(
            'yyyy/MM/dd'
            'yyyy/m/d'
            'yy/m/d'
            'yyyyMMdd'
        )

        # 適当な値で初期化
        [datetime]$parsedDate = [datetime]::MinValue

        # 変換して $parsedDate へ。失敗したら $parseSuccess が $false。
        [bool]$parseSuccess = [datetime]::TryParseExact(
                $userInputDate, 
                $dateFormats,
                [Globalization.DateTimeFormatInfo]::CurrentInfo,
                [Globalization.DateTimeStyles]::AllowWhiteSpaces,
                [ref]$parsedDate
            )

        if ($parseSuccess) {
            #Write-Host ('Parse success. input = {0}' -f $userInputDate)
            return $parsedDate.ToShortDateString();
        } else {
            #Write-Host ('Parse fail. input = {0}' -f $userInputDate)
            return "";
        }

        return "";
    }

    # ------------------------------------------------------------------------------------------------------------
    # カラーコンボボックスの色に応じてラベルの色を変更する
    # ------------------------------------------------------------------------------------------------------------
    SetStickyNoteColor([ComboBox]$cbo){
        $form  = $cbo.FindForm();
        $form.lblStickyNote.BackColor = $form._GetColor($cbo.Text);
        $selectedNode = $form.tvTasks.SelectedNode;
        if($selectedNode -ne $null) {$selectedNode.BackColor =$form.lblStickyNote.BackColor; }
    }

    # ------------------------------------------------------------------------------------------------------------
    # 区分に応じて色のColorインスタンスを取得する
    # ------------------------------------------------------------------------------------------------------------
    [Color]_GetColor([string]$strColor) {
        if ($strColor -eq $script:LABELCOLOR_RED) {
            return [System.Drawing.Color]::FromArgb(248, 91, 89);
        } elseif ($strColor -eq $script:LABELCOLOR_PINK) {
            return [System.Drawing.Color]::FromArgb(255 ,189 , 255);
        } elseif ($strColor -eq $script:LABELCOLOR_PURPLE) {
            return [System.Drawing.Color]::FromArgb(198,133,255);
        } elseif ($strColor -eq $script:LABELCOLOR_ORANGE) {
            return [System.Drawing.Color]::FromArgb(255,176,104);
        } elseif ($strColor -eq $script:LABELCOLOR_YELLOW) {
            return [System.Drawing.Color]::FromArgb(248, 255, 89);;
        } elseif ($strColor -eq $script:LABELCOLOR_LIGHTBLUE) {
            return [System.Drawing.Color]::FromArgb(32,241,234);
        } elseif ($strColor -eq $script:LABELCOLOR_BLUE) {
            return [System.Drawing.Color]::FromArgb(124, 124, 255);;
        } elseif ($strColor -eq $script:LABELCOLOR_GREEN) {
            return [System.Drawing.Color]::FromArgb(167, 255, 156);
        }
        return [System.Drawing.Color]::FromArgb(255, 255, 255);
    }

    # ------------------------------------------------------------------------------------------------------------
    # Nodeの内容をフォーム変数に格納しておく
    # 連想配列に格納しておくことで、参照型であるClassを名前ですぐにインスタンスを取得し、高速にアクセスできる
    # ------------------------------------------------------------------------------------------------------------
    SetSystemKeyValues([string] $strFullPath,[TreeNode]$tnTgtNode){
        $this.fdicNodes.Add($strFullPath,$tnTgtNode);
        $this.fdicNodesById.Add($strFullPath.Substring($strFullPath.length- 17,17),$tnTgtNode);
    }

    # ------------------------------------------------------------------------------------------------------------
    # パスからタスクのIDを取得する(yyyyMMddHHmmssがID)
    # ------------------------------------------------------------------------------------------------------------
    [string] GetIdFromPath([string]$strFolderPath){
        return $strFolderPath.Substring($strFolderPath.Length - 17,17);
    }

    # ------------------------------------------------------------------------------------------------------------
    # あるTreeNodeが別のTreeNodeの子ノードか調べる
    #  引数1:親ノードか調べるTreeNode
    #  引数2:子ノードか調べるTreeNode
    #  戻り値:子ノードの時はTrue
    # ------------------------------------------------------------------------------------------------------------
    [bool] IsChildNode([TreeNode] $parentNode, [TreeNode] $childNode)
    {
        if ($childNode.Parent -eq $parentNode) {
            return $true;
        } elseif ($childNode.Parent -ne $Null) {
            return $this.IsChildNode($parentNode, $childNode.Parent);
        } else {
            return $false;
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # DataGridViewの初期設定を実施
    # ------------------------------------------------------------------------------------------------------------
    DataGridViewInit(){
        
        $this.dgv.Columns.Clear();
        
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_TRKDATETIME,"登録日時",120,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_CREATEIONDATETIME);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_KBN,"区分",50,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_PATTERN);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTROL,"コントロール",70,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_CONTROL);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_HOSTNAME,"PC名",80,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_USERNAME);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS,"内容",280,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_HISTORY_HISTORYCONTENTS);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_ID,"ID",280,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_HISTORY_ID);
        $dc.Visible=$False;
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_HISTORY_ID,"履歴ID",280,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_HISTORY_HISTORYID);
        $dc.Visible=$False;
        $this.dgv.Columns.Add($dc)

        # $dt = New-Object System.Data.DataTable;
        # $dt.Columns.Add("strInsDateTime",[string])
        # $dt.Columns.Add("strKbn",[string])
        # $dt.Columns.Add("strHostName",[string])
        # $dt.Columns.Add("strContents",[string])

        # $dr = $dt.NewRow();
        # $dr["strInsDateTime"] ="2023/12/16 12:10:05";
        # $dr["strKbn"] ="自動";
        # $dr["strHostName"] = (Get-ChildItem Env:\USERNAME).Value;
        # $dr["strContents"] ="データ更新" ;
        # $dt.Rows.Add($dr);

        $this.dgv.DataSource = $null;

    }

    # ------------------------------------------------------------------------------------------------------------
    # DataGridViewのColumnを取得する
    # ------------------------------------------------------------------------------------------------------------
    [DataGridViewTextBoxColumn]GetDataGridColumnText([string] $strName,[string]$strHeaderText,[int]$intWidth,[string]$strCellTextAligment,[string]$strDataPropName) {
        $dc = New-Object DataGridViewTextBoxColumn ;
        $dc.Name = $strName;
        $dc.HeaderText = $strHeaderText;
        $dc.Width = $intWidth;
        $dc.DefaultCellStyle.Alignment = $strCellTextAligment;
        $dc.HeaderCell.Style.Alignment = "MiddleCenter";
        $dc.ReadOnly=$True;
        $dc.AutoSizeMode = "NotSet"      # 処理速度向上
        $dc.SortMode = "NotSortable";    # 並び替えを行わないようにすることでヘッダのテキストを中央寄せにできる
        $dc.DataPropertyName = $strDataPropName;
        return $dc;
    }

    # ------------------------------------------------------------------------------------------------------------
    # Menuコントロール設定処理
    # ------------------------------------------------------------------------------------------------------------
    MenuControlInit(){
        $this.menuFormMain.SuspendLayout()

        #「ファイル(&F)」メニュー項目を作成する
        $fileMenuItem = New-Object ToolStripMenuItem;
        $fileMenuItem.Text = "ファイル(&F)";
        $this.menuFormMain.Items.Add($fileMenuItem);

        #「上書き保存(&S)」メニュー項目を作成する
        $saveMenuItem = New-Object ToolStripMenuItem;
        $saveMenuItem.Text = "上書き保存(&S)";
        $fileMenuItem.DropDownItems.Add($saveMenuItem);

        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $fileMenuItem.DropDownItems.Add($sepa);

        #「終了(&X)」メニュー項目を作成する
        $closeMenuItem = New-Object ToolStripMenuItem;
        $closeMenuItem.Text = "終了(&X)";
        $fileMenuItem.DropDownItems.Add($closeMenuItem);

        #「ファイル(&F)」メニュー項目を作成する
        $operateMenuItem = New-Object ToolStripMenuItem;
        $operateMenuItem.Text = "操作(&E)";
        $this.menuFormMain.Items.Add($operateMenuItem);

        #「再描画(&R)」メニュー項目を作成する
        $refreshMenuItem = New-Object ToolStripMenuItem;
        $refreshMenuItem.Text = "再描画(&R)";
        $refreshMenuItem_Click_RefreshTreeView={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $form.RefreshTreeViewNodes();
        }
        $refreshMenuItem.add_Click($refreshMenuItem_Click_RefreshTreeView);
        $operateMenuItem.DropDownItems.Add($refreshMenuItem);

        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $operateMenuItem.DropDownItems.Add($sepa);

        #「圧縮」メニュー項目を作成する
        $ArchiveMenuItem = New-Object ToolStripMenuItem;
        $ArchiveMenuItem.Text = "圧縮";
        $ArchiveMenuItem_Click={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            # フォルダパスをすべて取得し、並び替えを行う
            # $directrys = [System.IO.Directory]::GetDirectories($this.GetDataFolderPath(), "*", [System.IO.SearchOption]::AllDirectories);
            # $directrys = $directrys | Sort-Object 
            # $parentNode = New-Object TreeNode;
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ return;}

            # Zipファイルを作成する
            $dicInfo = New-Object System.IO.DirectoryInfo($selectedTask.Tag);
            $strZipPath = $dicInfo.Parent.FullName + "\" + $form.GetIdFromPath($dicInfo.FullName) + ".zip";
            Compress-Archive -Path $dicInfo.FullName -DestinationPath $strZipPath -Force
            
            # 配下の.xmlファイルを全て一つのファイル(TaskArchive_[ID].xml)にまとめる
            # TaskArchive_[ID].xmlも存在している可能性があるのでそれぞれを取得して一つのリストにまとめる
            $fileInfo_Task = $dicInfo.GetFiles($script:DATA_FILE_NAME,[System.IO.SearchOption]::AllDirectories);
            $fileInfo_Archive = $dicInfo.GetFiles($script:DATA_ARCHIVE_FILE_NAME+"*",[System.IO.SearchOption]::AllDirectories);
            $lstAllFileInfo = [System.Collections.Generic.List[System.IO.FileInfo]]::new();
            $lstAllFileInfo.AddRange($fileInfo_Task);
            $lstAllFileInfo.AddRange($fileInfo_Archive);

            # xmlファイルをまとめるためのDataSet、DataTableを作成する
            $dsAll = New-Object System.Data.DataSet;
            $dtContents = New-Object System.Data.DataTable;
            $dtHistory = New-Object System.Data.DataTable;
            $dtContents = $form.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT].Clone();
            $dtHistory = $form.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_HISTORY].Clone();
            
            # アーカイブファイル用の追加項目。アーカイブされたファイルのTask.xmlファイルの相対パスを設定し、検索画面のインデントの計算に利用する
            $dtContents.Columns.Add($script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH,[string]);
            
            # Task.xml→TaskArchive_[ID].xmlの順で、ディレクトリの親子関係の順に並ぶようにするPropertyを指定して並び替えを行い、
            $filesSorted = $lstAllFileInfo | Sort-Object -Property DirectoryName,Name  

            #  ファイルを読み込んでテーブルごとに一つのテーブルにまとめる
            foreach ($path in $filesSorted) {
                $ds = New-Object System.Data.DataSet;
                $ds.ReadXml($path.FullName);
                foreach ($dr in $ds.Tables[$script:DATA_TABLE_NAME_CONTENT].Rows) {
                    $drContents = $dtContents.NewRow();
                    $drContents.ItemArray = $dr.ItemArray;
                    if ($path.Name -ne $script:DATA_FILE_NAME){ # アーカイブファイルの場合はすでに相対パスが設定されている
                        $drContents[$script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH] = $path.DirectoryName.Replace($dicInfo.Parent.FullName + "\","") + "\" + $dr[$script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH];
                    } else {
                        $drContents[$script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH] = $path.DirectoryName.Replace($dicInfo.Parent.FullName + "\","");
                    }
                    $dtContents.Rows.Add($drContents);
                }
                foreach ($dr in $ds.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows) {
                    $drHistory = $dtHistory.NewRow();
                    $drHistory.ItemArray = $dr.ItemArray;
                    $dtHistory.Rows.Add($drHistory);
                }
            }
            #  作成したDataTableをひとつのDataSetにまとめて書き込みする
            $dsAll.Tables.Add($dtContents);
            $dsAll.Tables.Add($dtHistory);
            $dsAll.WriteXml($dicInfo.Parent.FullName + "\" + $script:DATA_ARCHIVE_FILE_NAME +  $form.GetIdFromPath($dicInfo.FullName) + ".xml");
            
            # 圧縮したあとのフォルダは削除する
            Remove-Item -Path $dicInfo.FullName -Recurse;

            # フォルダを削除しているので再描画を実施
            $form.RefreshTreeViewNodes();
            
            [System.Windows.Forms.MessageBox]::Show("選択されたタスクをアーカイブしました。アーカイブされたファイルは、検索画面で確認できます。元に戻す場合は、検索画面から「復元」処理を行ってください。", "メッセージ")

        }

        $ArchiveMenuItem.add_Click($ArchiveMenuItem_Click);
        $operateMenuItem.DropDownItems.Add($ArchiveMenuItem);

        # $ThawingMenuItem = New-Object ToolStripMenuItem;
        # $ThawingMenuItem.Text = "解凍";
        # $ThawingMenuItem_Click={
        #     $sender = $args[0];
        #     $e = $args[1];
        #     $form = $sender.OwnerItem.Owner.FindForm();
        # }
        # $ThawingMenuItem.add_Click($ThawingMenuItem_Click);
        # $operateMenuItem.DropDownItems.Add($ThawingMenuItem);

        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $operateMenuItem.DropDownItems.Add($sepa);

        #「検索」メニュー項目を作成する
        $searchMenuItem = New-Object ToolStripMenuItem;
        $searchMenuItem.Text = "検索";
        $searchMenuItem_Click={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $frmSearch = [frm020_000_Search]::new();
            $frmSearch.fstrCurrentPath = $form.fstrCurrentPath;
            #$frmSearch.Owner = $form;
            $frmSearch.Top = $form.Top + 30;
            $frmSearch.Left = $form.Left + 30;
            $frmSearch.StartPosition = [FormStartPosition]::Manual;
            $frmSearch.frmProject = $form;
            $frmSearch.Show();
        }
        $searchMenuItem.add_Click($searchMenuItem_Click);
        $operateMenuItem.DropDownItems.Add($searchMenuItem);
        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $operateMenuItem.DropDownItems.Add($sepa);

        #「下のレベルに追加(&A)」メニュー項目を作成する
        $addMenuItem = New-Object ToolStripMenuItem;
        $addMenuItem.Text = "下のレベルに追加(F1)(&A)";
        $addMenuItem_Click_AddNode_Under={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ $form.AddTaskNode($form.GetDataFolderPath(), $false);}
            else {$form.AddTaskNode($selectedTask.Tag, $false);}
            $form.ClearInit();
        }
        $addMenuItem.add_Click($addMenuItem_Click_AddNode_Under);
        $operateMenuItem.DropDownItems.Add($addMenuItem);

        #「同じレベルに追加(&M)」メニュー項目を作成する
        $addSameMenuItem = New-Object ToolStripMenuItem;
        $addSameMenuItem.Text = "同じレベルに追加(F2)(&M)";
        $addSameMenuItem_Click_AddNode_Same={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ 
                # Nodeが一つもない場合は必ず下のレベルに追加にする
                $form.AddTaskNode($form.GetDataFolderPath(), $false);
            }
            else {$form.AddTaskNode($selectedTask.Tag, $true);}
            
            $form.ClearInit();

        }
        $addSameMenuItem.add_Click($addSameMenuItem_Click_AddNode_Same);
        $operateMenuItem.DropDownItems.Add($addSameMenuItem);

        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $operateMenuItem.DropDownItems.Add($sepa);

        #「削除(&D)」メニュー項目を作成する
        $deleteMenuItem = New-Object ToolStripMenuItem;
        $deleteMenuItem.Text = "削除(&D)";
        $deleteMenuItem_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ return ; }
            else {$form.DelTaskNode($selectedTask.Tag,$true);}
            $form.ClearInit();
        }
        $deleteMenuItem.add_Click($deleteMenuItem_Click);
        $operateMenuItem.DropDownItems.Add($deleteMenuItem);

        # セパレータ
        $sepa = New-Object ToolStripSeparator;
        $operateMenuItem.DropDownItems.Add($sepa);

        #「上へ(&U)」メニュー項目を作成する
        $upMenuItem = New-Object ToolStripMenuItem;
        $upMenuItem.Text = "タスクを上へ(F3)(&U)";
        $upMenuItem_Click_MoveUp={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ 
                #[System.Windows.Forms.MessageBox]::Show("未選択です", "結果")
                return;
            }
            else {
                $form.MoveTask($selectedTask,$True);
            }
            #$form.ClearInit();
        }
        $upMenuItem.add_Click($upMenuItem_Click_MoveUp);
        $operateMenuItem.DropDownItems.Add($upMenuItem);

        #「下へ(&U)」メニュー項目を作成する
        $downMenuItem = New-Object ToolStripMenuItem;
        $downMenuItem.Text = "タスクを下へ(F4)(&D)";
        $upMenuItem_Click_MoveDown={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.OwnerItem.Owner.FindForm();
            $selectedTask = $form.tvTasks.SelectedNode;
            if ($selectedTask -eq $null){ 
                #[System.Windows.Forms.MessageBox]::Show("未選択です", "結果")
                return;
            }
            else {
                $form.MoveTask($selectedTask,$False);
            }
            #$form.ClearInit();
        }
        $downMenuItem.add_Click($upMenuItem_Click_MoveDown);
        $operateMenuItem.DropDownItems.Add($downMenuItem);

        # フォームにMenuStripを追加する
        $this.Controls.Add($this.menuFormMain);

        # フォームのメインメニューとする
        $this.MainMenuStrip = $this.menuFormMain;

        # レイアウトロジックを再開する
        $this.menuFormMain.ResumeLayout($false);
        $this.menuFormMain.PerformLayout();

    }

    # ------------------------------------------------------------------------------------------------------------
    # 選択されているNodeの下の階層にフォルダを追加したうえで、TreeViewのNodeに追加する
    # ------------------------------------------------------------------------------------------------------------
    RefreshTreeViewNodes() {
        # 展開状態を覚えておく
        $strSelectedNode = "";
        $selectedNode = $this.tvTasks.SelectedNode;
        if ($selectedNode -ne $null) {$strSelectedNode = $selectedNode.Tag.Substring($selectedNode.Tag.length-17,17)};
        $lstExpandNodes = New-Object 'System.Collections.Generic.List[string]';
        foreach ($key in $this.fdicNodes.Keys) {
            [TreeNode] $node = $this.fdicNodes[$key];
            if ($node.IsExpanded -eq $true) {
                $lstExpandNodes.Add($key.Substring($key.length-17,17));
            }
        }

        # クリア処理
        $this.SuspendLayout();
        $this.tvTasks.SuspendLayout();
        $this.tvTasks.Nodes.Clear();
        $this.fdicNodes.Clear();
        $this.fdicNodesById.Clear();

        # フォルダパスをすべて取得し、並び替えを行う
        $directrys = [System.IO.Directory]::GetDirectories($this.GetDataFolderPath(), "*", [System.IO.SearchOption]::AllDirectories);
        $directrys = $directrys | Sort-Object 
        $parentNode = New-Object TreeNode;

        foreach ($path in $directrys){
            $dicInfo = New-Object System.IO.DirectoryInfo($path);
            $dicParentInfo = New-Object System.IO.DirectoryInfo($dicInfo.Parent.FullName);
            
            $node = New-Object TreeNode;
            
            # TreeNodeの値やフォントを設定する
            [System.Data.DataRow]$dr = $this.GetTaskDataRow($dicInfo.FullName)

            #  タイトル
            if ($dr[$script:COLNAME_CONTENTS_TITLE] -eq "") { $node.Text= "[No Title]";}
            else { $node.Text= $dr[$script:COLNAME_CONTENTS_TITLE]; }

            #  進捗状態に合わせてフォントを変更
            #  背景などのフォントスタイル設定のテスト
            $this._SetTreeNodeStyle($node,$dr[$script:COLNAME_CONTENTS_STATUS],$dr[$script:COLNAME_CONTENTS_LIMITDAY],$dr[$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT],$dr[$script:COLNAME_CONTENTS_COLORLABEL])

            # Nodeのタグ値にキーとなるパスを設定する
            $node.Tag = $path;

            # フォーム変数に覚えている全Nodeリストに追加する(忘れないようにすること)
            $this.SetSystemKeyValues($path.ToString(),$node);

            # タスクを追加する
            if ($dicParentInfo.FullName -eq $this.GetDataFolderPath() ){
                $this.tvTasks.Nodes.Add($node);
            } else {
                # 既に追加されているものから探してくる
                $parentNode = $this.fdicNodes[$dicParentInfo.FullName];
                $parentNode.Nodes.Add($node);
            }
        }

        # 事前に保存している内容で設定する(展開状況と選択ノードを元に戻す)
        foreach ($strId in $lstExpandNodes) {
            [TreeNode] $node = $this.fdicNodesById[$strId];
            if($node -ne $null) { $node.Expand(); }
        }
        if ($strSelectedNode -ne "") 
        {
            $this.tvTasks.SelectedNode = $this.fdicNodesById[$strSelectedNode];
        };


        # 描画を開始
        $this.tvTasks.ResumeLayout();
        $this.ResumeLayout();

    }

    # ------------------------------------------------------------------------------------------------------------
    # Nodeのスタイルを設定する
    # ------------------------------------------------------------------------------------------------------------
    _SetTreeNodeStyle([TreeNode]$node,[string] $strStatus,[string] $strLimitDay,[string] $strAlertDayCount,[string] $strColorPattern) {
        # 初期化
        $node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Regular) ;
        $node.ForeColor = "Black";
        
        # 状態によってフォントを変更する
        if ($strStatus -eq $script:STATUS_DONE) {
            $node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Strikeout) ;
        } elseif ($strStatus -eq $script:STATUS_DOING) {
            # ItalicとBoldを同時設定する場合は括弧で指定し、カンマで区切る([System.Drawing.FontStyle]::Italic,[System.Drawing.FontStyle]::Bold) = C#のFontStyle.Italic | FontStyle.Bold)
            $node.NodeFont = New-Object Drawing.Font($this.Font, ([System.Drawing.FontStyle]::Italic,[System.Drawing.FontStyle]::Bold)) ;
            $node.ForeColor = "Blue";
        }

        $strLimitDay = $this.GetDateTryConvertFromString($strLimitDay);
        if (($strLimitDay -ne "") -And ($strStatus -ne $script:STATUS_DONE)) {
            [datetime]$parsedDate = [datetime]::Parse($strLimitDay);
            $intConvertCount = 0;
            if ([double]::TryParse($strAlertDayCount,[ref]$intConvertCount) -eq $true){
                $parsedDate = $parsedDate.AddDays($intConvertCount * -1);
            }

            [datetime]$now = [datetime]::Now;
            if ($parsedDate.ToShortDateString() -le $now.ToShortDateString()) {
                $node.NodeFont = New-Object Drawing.Font($this.Font, [System.Drawing.FontStyle]::Bold) ;
                $node.ForeColor = "Red";
            }
        }
        
        # ノードの背景色を設定
        if($strColorPattern -ne "") {$node.BackColor = $this._GetColor($strColorPattern); } 

    }

    # ------------------------------------------------------------------------------------------------------------
    # 履歴を追加する
    # ------------------------------------------------------------------------------------------------------------
    _AddHistory([string]$strContents,[bool]$blnAutoHistory) {
        if ($this.fdsCurrentData -eq $null) {return;}
        if ($this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT] -eq $null) {return;}

        if ($blnAutoHistory -eq $True) {
            [string]$strChangeLog = "";

            $dt = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT];
            
            # タイトル
            if ($this.txtTitle.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_TITLE]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_TITLE] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtTitle.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"タイトル",$strChangeLog);
            };

            # 期限
            if ($this.txtLimit.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITDAY]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITDAY] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtLimit.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"期限",$strChangeLog);
            };

            # 期限前通知
            if ($this.txtAlertDayCount.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtAlertDayCount.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"期限前通知",$strChangeLog);
            };

            # 進捗状況
            if ($this.cboStatus.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_STATUS]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_STATUS] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.cboStatus.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"進捗状況",$strChangeLog);
            };

            # カラーラベル
            if ($this.cboColorLabel.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_COLORLABEL]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_COLORLABEL] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.cboColorLabel.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"進捗状況",$strChangeLog);
            };

            # カラーラベル
            if ($this.txtMember.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_MEMBER]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_MEMBER] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtMember.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"担当",$strChangeLog);
            };

            # 分類
            if ($this.txtClass.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_CLASS]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_CLASS] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtClass.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"分類",$strChangeLog);
            };

            # 内容
            if ($this.txtContents.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_CONTENTS]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_CONTENTS] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtContents.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"内容",$strChangeLog);
            };

            # 備考
            if ($this.txtNote.Text -ne $dt.Rows[0][$script:COLNAME_CONTENTS_NOTE]){
                $strChangeLog = "";
                $strChangeLog += $dt.Rows[0][$script:COLNAME_CONTENTS_NOTE] + "`r`n";
                $strChangeLog += "↓↓↓↓↓↓`r`n";
                $strChangeLog += $this.txtNote.Text + "`r`n";
                $this._AddRow_Hisotory($script:PATTERN_CHANGELOG,"備考",$strChangeLog);
            };

        } else {
            if ($strContents -ne "") {
                $this._AddRow_Hisotory($script:PATTERN_COMMENT,"コメント",$this.txtComments.Text);
            } else {
                $this._AddRow_Hisotory($script:PATTERN_AUTO,"",$strContents);
            }
        }

    }

    # ------------------------------------------------------------------------------------------------------------
    # 履歴一覧に値を追加する
    # ------------------------------------------------------------------------------------------------------------
    _AddRow_Hisotory([string]$strPattern,[string]$strControl,[string]$strHistoryContents){
        $dr = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_HISTORY].NewRow();
        $dr[$script:COLNAME_HISTORY_PATTERN] = $strPattern;
        $dr[$script:COLNAME_HISTORY_CONTROL] = $strControl;
        $dr[$script:COLNAME_HISTORY_CREATEIONDATETIME] = Get-Date -Format "yyyy/MM/dd HH:mm:ss";
        $dr[$script:COLNAME_HISTORY_USERNAME] = (Get-ChildItem Env:\USERNAME).Value;
        $dr[$script:COLNAME_HISTORY_HISTORYCONTENTS] = $strHistoryContents;
        $dr[$script:COLNAME_HISTORY_ID] = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT].Rows[0][$script:COLNAME_CONTENTS_ID];
        $dr[$script:COLNAME_HISTORY_HISTORYID] = Get-Date -Format "yyyyMMddHHmmssfff";
        $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows.Add($dr);
    }

    # ------------------------------------------------------------------------------------------------------------
    # 選択されているNodeの下の階層にフォルダを追加したうえで、TreeViewのNodeに追加する
    #  RefreshTreeViewNodesを使うとTreeViewのNodeがすべて再構築されるので、選択状態が消える
    # 毎回最新を取得して選択状態を取得したほうが安全か・・・?
    # ------------------------------------------------------------------------------------------------------------
    AddTaskNode([string] $strFolderPath,[bool] $blnSameLevel) {
        $strNow = Get-Date -Format "yyyyMMddhhmmssfff";
        $dicInfo = New-Object System.IO.DirectoryInfo($strFolderPath);
        if ($blnSameLevel -eq $true) {
            $dicInfo = $dicInfo.Parent;
        }
        
        $strFolderNo =  "0000" + ($dicInfo.GetDirectories().Count + 1) ;
        $strFolderNo = $strFolderNo.Substring($strFolderNo.Length - 4 ,4);
        $strNewFolderPath = $dicInfo.FullName + "\" +  $strFolderNo +  "_" + $strNow ;

        New-Item $strNewFolderPath -ItemType Directory;

        # Nodeを追加する
        $dicInfo = New-Object System.IO.DirectoryInfo($strNewFolderPath);
        $node = New-Object TreeNode;
        #$node.Text= $this.GetTaskTitle($dicInfo.FullName);
        $node.Tag = $dicInfo.FullName;
        # 全Nodeリストに追加する(忘れないようにすること)
        $this.SetSystemKeyValues($dicInfo.FullName,$node);
        # $this.fdicNodes.Add($dicInfo.FullName,$node);
        # $this.fdicNodesById.Add($dicInfo.FullName.Substring($dicInfo.FullName.length-14,14),$node);

        # 既に追加されているものから探してくる
        if ($dicInfo.Parent.FullName -eq $this.GetDataFolderPath() ){
            $this.tvTasks.Nodes.Add($node);
        } else {
            # 既に追加されているものから探してくる
            $parentNode = $this.fdicNodes[$dicInfo.Parent.FullName];
            $parentNode.Expand();
            $parentNode.Nodes.Add($node);
        }

        # 画面を初期化する
        $this.ClearInit();

        # ファイルを保存する
        $this.SaveFile($dicInfo.FullName);

        # TreeViewのNodeを再構築する
        $this.RefreshTreeViewNodes();

        # 追加したNodeを選択状態にすることで現在選択されているNodeの内容が保存される
        $this.tvTasks.SelectedNode = $this.fdicNodesById[$node.Tag.Substring($node.Tag.Length - 17,17)];
        # すぐに入力できるようにフォーカスを設定
        $this.txtTitle.Focus();
    }

    # ------------------------------------------------------------------------------------------------------------
    # タスクを削除(ゴミ箱へ移動)する
    # ------------------------------------------------------------------------------------------------------------
    DelTaskNode([string] $strFolderPath ,[bool]$blnShowMsg){

        #『OK』と『キャンセル』ボタンを表示する場合
        if ($blnShowMsg -eq $true) {
            $result = [System.Windows.Forms.MessageBox]::Show("選択されたタスクをゴミ箱に移動してもよろしいですか?", "確認", [System.Windows.Forms.MessageBoxButtons]::OKCancel, [System.Windows.Forms.MessageBoxIcon]::Question,[System.Windows.Forms.MessageBoxDefaultButton]::Button2)
        } else {
            $result = [DialogResult]::OK;
        }

        # $this.ShowMsgbox("選択されたタスクをゴミ箱に移動してもよろしいですか?", , [System.Windows.Forms.MessageBoxIcon]::Question)

        if ($result -eq [DialogResult]::OK){
            $shell = New-Object -ComObject Shell.Application
            $trash = $shell.NameSpace(10)
            $trash.MoveHere($strFolderPath)

            # 画面を初期化する
            $this.ClearInit();

            # TreeViewのNodeを再構築する
            $this.RefreshTreeViewNodes();

        }

    }

    # ------------------------------------------------------------------------------------------------------------
    # タスクを移動する
    # ------------------------------------------------------------------------------------------------------------
    MoveTask([TreeNode]$selectedTask,[bool]$blnMoveUp) {
        $tnParent = $selectedTask.Parent;
        
        if ($tnParent -eq $null){return;}
        if ($tnParent.Nodes -eq $null){return;}

        $index = $tnParent.Nodes.IndexOf($selectedTask);
        $insertIdx = 0;
        if ($blnMoveUp) {
            $insertIdx = $index - 1;
            if ($insertIdx -lt 0 ) { 
                [System.Windows.Forms.MessageBox]::Show("これ以上上に行けません", "エラー");
                return;
                }
        } else {
            $insertIdx = $index + 1;
            if ($insertIdx -gt $tnParent.Nodes.Count - 1 )
            {
                [System.Windows.Forms.MessageBox]::Show("これ以上下に行けません", "エラー");
                return;
            }
        }

        $selectedTask.Remove();
        $tnParent.Nodes.Insert($insertIdx, $selectedTask);
        $this.tvTasks.SelectedNode = $selectedTask;

        for ($i = 0; $i -lt $tnParent.Nodes.Count; $i++) {
            $dicInfo = New-Object System.IO.DirectoryInfo($tnParent.Nodes[$i].Tag);
            $strNo = ("0000" + ( $i + 1 ));
            $strNo = $strNo.Substring($strNo.Length - 4 , 4 );
            $strNewFolderName = $strNo + "_" + $dicInfo.Name.Substring($dicInfo.Name.Length - 17 , 17);
            
            # フォルダをリネーム(番号が変わる場合のみ)
            if ($dicInfo.Name -ne $strNewFolderName) {
                Rename-Item $dicInfo.FullName $strNewFolderName
            }
        }

        # TreeViewを再構築する
        $this.RefreshTreeViewNodes()

    }

    # ------------------------------------------------------------------------------------------------------------
    # IDをキーにNodeを選択する
    # ------------------------------------------------------------------------------------------------------------
    SelectNodeById([string]$strId){
        if ( $this.fdicNodesById.ContainsKey($strId) -eq $true){
            $this.tvTasks.SelectedNode = $this.fdicNodesById[$strId];

            if ($this.tvTasks.SelectedNode.Parent.IsExpanded -eq $false){
                $this.tvTasks.SelectedNode.Parent.Expand();
            }
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # ファイルを開いてタスクのタイトルを取得する
    # ------------------------------------------------------------------------------------------------------------
    [string]GetTaskTitle([string]$strDicPath) {
        if ($this.OpenFile($strDicPath) -eq $true ){
            $dt = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT];
            if ($dt.Rows[0][$script:COLNAME_CONTENTS_TITLE] -eq "") { return "[No Title]" } # Titleが空白の場合にTreeView上で選択できなくなるため
            else {return $dt.Rows[0][$script:COLNAME_CONTENTS_TITLE];}
        } else {
            return "[Not Exists Task.xml]" + $strDicPath;
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # ファイルを開いてタスクのデータを返す
    # ------------------------------------------------------------------------------------------------------------
    [System.Data.DataRow]GetTaskDataRow([string]$strDicPath) {
        if ($this.OpenFile($strDicPath) -eq $true ){
            $dt = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT];
            return $dt.Rows[0];
        } else {
            return $null;
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # ファイルを開いて画面に値を設定する
    # ------------------------------------------------------------------------------------------------------------
    SetDataFromFile([string]$strDicPath){
        
        $this.ClearInit();

        if ($this.OpenFile($strDicPath) -eq $true ){
            $dt = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_CONTENT];
            $this.txtTitle.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_TITLE];
            $this.txtLimit.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITDAY];
            $this.txtAlertDayCount.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT];
            $this.cboStatus.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_STATUS];
            $this.cboColorLabel.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_COLORLABEL];
            $this.lblStickyNote.BackColor = $this._GetColor($this.cboColorLabel.Text);
            $this.txtMember.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_MEMBER];
            $this.txtClass.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_CLASS];
            $this.txtCreateDateTime.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_CREATEIONDATETIME];
            $this.txtContents.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_CONTENTS];
            $this.txtNote.Text = $dt.Rows[0][$script:COLNAME_CONTENTS_NOTE];
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # 画面上の値をクリアする
    # ------------------------------------------------------------------------------------------------------------
    ClearInit(){
        $this.txtTitle.Text = "";
        $this.txtLimit.Text = "";
        $this.txtAlertDayCount.Text = "3";
        $this.cboStatus.Text = "作業前";
        $this.cboColorLabel.Text = "";
        $this.txtMember.Text = "";
        $this.txtClass.Text = "";
        $this.txtCreateDateTime.Text = "";
        $this.txtContents.Text = "";
        $this.txtNote.Text = "";

        $this.txtHistoryContents.Text = "";
        $this.txtComments.Text = "";

        $this.DataGridViewInit();
    }

    # ------------------------------------------------------------------------------------------------------------
    # ファイルの内容を開く
    # ------------------------------------------------------------------------------------------------------------
    [bool]OpenFile([string]$strDicPath) {
        $strFilePath = $strDicPath + "\" + $script:DATA_FILE_NAME;
        #Write-Host ('FilePath  {0}' -f $strFilePath)

        if ((Test-Path $strFilePath) -eq $true) {
            $ds = New-Object System.Data.DataSet;
            $ds.ReadXml($strFilePath);
            $this.fdsCurrentData = $ds;
            if ($this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_HISTORY] -eq $null) {return $false;}

            $this.dgv.DataSource = $this.fdsCurrentData.Tables[$script:DATA_TABLE_NAME_HISTORY];

            $this.dgv.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
            foreach($dgvRow in $this.dgv.Rows){
                if ($dgvRow.Cells[$script:DGV_COLNAME_KBN].Value -eq $script:PATTERN_CHANGELOG) {$dgvRow.Visible=$this.chkShowHistory.Checked;}
                if ($dgvRow.Cells[$script:DGV_COLNAME_KBN].Value -eq $script:PATTERN_COMMENT) {
                    foreach ($cell in $dgvRow.Cells){
                        $cell.Style.ForeColor = "Blue";
                    }
                }
            }
            return $true;
        } else {
            return $false;
        }
    }    


    # ------------------------------------------------------------------------------------------------------------
    # 履歴一覧のコメント行を削除する
    # ------------------------------------------------------------------------------------------------------------
    DeleteRowIndgv() {

        if ( $this.dgv.CurrentRow.Cells[$script:DGV_COLNAME_KBN].Value -ne $script:PATTERN_COMMENT) { 
            [System.Windows.Forms.MessageBox]::Show("削除できるのはコメント行のみです", "エラー")
            return;
        }

        $result = [System.Windows.Forms.MessageBox]::Show("選択された行を削除してもよろしいですか?削除した行は戻せません。", "確認", [System.Windows.Forms.MessageBoxButtons]::OKCancel, [System.Windows.Forms.MessageBoxIcon]::Question,[System.Windows.Forms.MessageBoxDefaultButton]::Button2)

        if ($result -eq [DialogResult]::OK){
            # データバインドでDataGridViewを表示しているのでDataSourceに指定されているDataTableを削除する必要がある
            $dt = $this.dgv.DataSource;
            $selectedDataRow = $this.dgv.CurrentRow.DataBoundItem;
            $dt.Rows.Remove($selectedDataRow.Row);
        }

        # DataTableを削除すると再バインドが起きて非表示にしている列が見えるようになってしまうため再度非表示にする
        # $this.dgv.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
        # foreach($dgvRow in $this.dgv.Rows){
        #     if ($dgvRow.Cells[$script:DGV_COLNAME_KBN].Value -eq $script:PATTERN_CHANGELOG) {$dgvRow.Visible=$this.chkShowHistory.Checked;}
        #     if ($dgvRow.Cells[$script:DGV_COLNAME_KBN].Value -eq $script:PATTERN_COMMENT) {
        #         foreach ($cell in $dgvRow.Cells){
        #             $cell.Style.ForeColor = "Blue";
        #         }
        #     }
        # }
        
        # データを保存。SaveFileをした際に再度OpenFileをしており、その中で行の非表示処理を再実行している
        $this.SaveFile($this.tvTasks.SelectedNode.Tag);
    }

    # ------------------------------------------------------------------------------------------------------------
    # 画面上の値をファイルに保存する
    # ------------------------------------------------------------------------------------------------------------
    SaveFile([string]$strDicPath) {
        $dicInfo = New-Object System.IO.DirectoryInfo($strDicPath);

        # 変更履歴を追加
        $this._AddHistory("",$true);

        $ds = New-Object System.Data.DataSet;
        $ds.DataSetName = "TaskDate";

        # コンテンツテーブル作成
        $dtContents = New-Object System.Data.DataTable;
        $dtContents.TableName = $script:DATA_TABLE_NAME_CONTENT;
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_ID,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_TITLE,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_LIMITDAY,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_STATUS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_COLORLABEL,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_MEMBER,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CLASS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CREATEIONDATETIME,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CONTENTS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_NOTE,[string]);

        # データを登録
        $strDateTime = $this.GetIdFromPath($strDicPath);
        $strDateTime = $strDateTime.Substring(0,4) + "/" + $strDateTime.Substring(4,2) + "/" + $strDateTime.Substring(6,2) + " " + $strDateTime.Substring(8,2) + ":" + $strDateTime.Substring(10,2) + ":" + $strDateTime.Substring(12,2) + ":" + $strDateTime.Substring(14,3) 
        $dr = $dtContents.NewRow();
        $dr[$script:COLNAME_CONTENTS_ID]=$this.GetIdFromPath($strDicPath);
        $dr[$script:COLNAME_CONTENTS_TITLE]=$this.txtTitle.Text;
        $dr[$script:COLNAME_CONTENTS_LIMITDAY]=$this.txtLimit.Text;
        $dr[$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT]=$this.txtAlertDayCount.Text;
        $dr[$script:COLNAME_CONTENTS_STATUS]=$this.cboStatus.Text;
        $dr[$script:COLNAME_CONTENTS_COLORLABEL]=$this.cboColorLabel.Text;
        $dr[$script:COLNAME_CONTENTS_MEMBER]=$this.txtMember.Text;
        $dr[$script:COLNAME_CONTENTS_CLASS]=$this.txtClass.Text;
        $dr[$script:COLNAME_CONTENTS_CREATEIONDATETIME]=$strDateTime;
        $dr[$script:COLNAME_CONTENTS_CONTENTS]=$this.txtContents.Text;
        $dr[$script:COLNAME_CONTENTS_NOTE]=$this.txtNote.Text;
        $dtContents.Rows.Add($dr);
        $ds.Tables.Add($dtContents);

        # 履歴テーブル作成
        $dtHistorys = New-Object System.Data.DataTable;
        $dtHistorys.TableName = $script:DATA_TABLE_NAME_HISTORY;
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_ID,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_HISTORYID,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_CREATEIONDATETIME,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_CONTROL,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_PATTERN,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_USERNAME,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_HISTORYCONTENTS,[string]);

        $dt_dgv = $this.dgv.DataSource;
        foreach ($dr_dgv in $dt_dgv.Rows) {
            $dr = $dtHistorys.NewRow();
            $dr[$script:COLNAME_HISTORY_ID]=$dr_dgv[$script:COLNAME_HISTORY_ID];
            $dr[$script:COLNAME_HISTORY_HISTORYID]=$dr_dgv[$script:COLNAME_HISTORY_HISTORYID];
            $dr[$script:COLNAME_HISTORY_PATTERN]=$dr_dgv[$script:COLNAME_HISTORY_PATTERN];
            $dr[$script:COLNAME_HISTORY_CREATEIONDATETIME]=$dr_dgv[$script:COLNAME_HISTORY_CREATEIONDATETIME];
            $dr[$script:COLNAME_HISTORY_CONTROL]=$dr_dgv[$script:COLNAME_HISTORY_CONTROL];
            $dr[$script:COLNAME_HISTORY_USERNAME]=$dr_dgv[$script:COLNAME_HISTORY_USERNAME];
            $dr[$script:COLNAME_HISTORY_HISTORYCONTENTS]=$dr_dgv[$script:COLNAME_HISTORY_HISTORYCONTENTS];
            $dtHistorys.Rows.Add($dr);
        }

        # 新規追加の場合は、新規登録された履歴を登録。履歴が0件だとエラーが発生する
        if ($dtHistorys.Rows.Count -eq 0 ) {
            $dr = $dtHistorys.NewRow();
            $dr[$script:COLNAME_HISTORY_ID] = $dtContents.Rows[0][$script:COLNAME_CONTENTS_ID];
            $dr[$script:COLNAME_HISTORY_HISTORYID] = Get-Date -Format "yyyyMMddHHmmssfff";
            $dr[$script:COLNAME_HISTORY_PATTERN]=$script:PATTERN_AUTO;
            $dr[$script:COLNAME_HISTORY_CREATEIONDATETIME] = Get-Date -Format "yyyy/MM/dd HH:mm:ss";
            $dr[$script:COLNAME_HISTORY_CONTROL]="-";
            $dr[$script:COLNAME_HISTORY_USERNAME] = (Get-ChildItem Env:\USERNAME).Value;
            $dr[$script:COLNAME_HISTORY_HISTORYCONTENTS]="新規作成";
            $dtHistorys.Rows.Add($dr);
        }

        $ds.Tables.Add($dtHistorys);
        $ds.WriteXml($dicInfo.FullName + "\" + $script:DATA_FILE_NAME);
        # 保存したファイルを再度開くことでfdsの内容を変更する
        $this.OpenFile($dicInfo.FullName)

    }    

    # ------------------------------------------------------------------------------------------------------------
    # データを保存しているフォルダを取得する
    # ------------------------------------------------------------------------------------------------------------
    [string] GetDataFolderPath(){
        return  ($this.fstrCurrentPath + "\Data");
    }

}



# ------------------------------------------------------------------------------------------------------------
#  検索画面
# ------------------------------------------------------------------------------------------------------------
Class frm020_000_Search :System.Windows.Forms.Form{
    #region Class変数
    [string]$fstrCurrentPath; # インスタンス後に設定される。$MyInvocation.MyCommandはスクリプト内で定義されており、ウォッチ式は見れるがクラスの中では取得できない。
    [System.Data.DataSet]$fdsCurrentSearchData ;
    [frm010_000_Projet]$frmProject;
    #endregion

    #region ↓↓↓↓↓  Design Start
    # 色:https://www.lab-nemoto.jp/www/leaflet_edu/else/ColorMaker.html
    #   ▼タイトルラベル
    $lblPatternTitle=[Label]@{  
        Location = [Point]::new(5,5);
        Size=[Size]::new(924,20);
        Text = “◆検索条件”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left,Right";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $lblFree=[Label]@{
        Location = [Point]::new(5,30);
        Size=[Size]::new(80,20);
        Text = “フリー検索”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $txtFree=[TextBox]@{
        Location = [Point]::new(88,30);
        Size=[Size]::new(180,20);
        Anchor="Top,Left";
        Text = “”;
    }

    $lblTitle=[Label]@{
        Location = [Point]::new(272,30);
        Size=[Size]::new(70,20);
        Text = “タイトル”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtTitle=[TextBox]@{
        Location = [Point]::new(345,30);
        Size=[Size]::new(140,20);
        Anchor="Top,Left";
        Text = “”;
    }

    $lblStatus =[Label]@{
        Location = [Point]::new(490,30);
        Size=[Size]::new(70,20);
        Text = “進捗状況”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $chkTodo=[CheckBox]@{
        Location = [Point]::new(565,32);
        Size=[Size]::new(30,20);
        # Anchor="Top,Left";
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “作業前”;
    }
    $chkDoing=[CheckBox]@{
        Location = [Point]::new(635,32);
        Size=[Size]::new(30,20);
        # Anchor="Top,Left";
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “作業中”;
    }
    $chkDone=[CheckBox]@{
        Location = [Point]::new(705,32);
        Size=[Size]::new(30,20);
        # Anchor="Top,Left";
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “作業完了”;
    }
    $lblClass =[Label]@{
        Location = [Point]::new(785,30);
        Size=[Size]::new(40,20);
        Text = “分類”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtClass=[TextBox]@{
        Location = [Point]::new(828,30);
        Size=[Size]::new(95,20);
        Anchor="Top,Left";
        Text = “”;
    }
    
    $lblLimit=[Label]@{
        Location = [Point]::new(5,53);
        Size=[Size]::new(80,20);
        Text = “期限”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $txtLimitStart=[TextBox]@{
        Location = [Point]::new(88,53);
        Size=[Size]::new(80,20);
        Anchor="Top,Left";
        Text = “”;
        ImeMode = "Off";
    }

    $lblLimitBetween=[Label]@{
        Location = [Point]::new(170,58);
        Size=[Size]::new(17,15);
        Text = “~”; 
        Anchor="Top,Left";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $txtLimitEnd=[TextBox]@{
        Location = [Point]::new(188,53);
        Size=[Size]::new(80,20);
        Anchor="Top,Left";
        Text = “”;
        ImeMode = "Off";
    }

    $lblColoer=[Label]@{
        Location = [Point]::new(272,53);
        Size=[Size]::new(70,20);
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Text = “色”; 
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }

    $chkNoColor=[CheckBox]@{
        Location = [Point]::new(348,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “なし”;
    }

    $chkRed=[CheckBox]@{
        Location = [Point]::new(400,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “赤”;
    }

    $chkPink=[CheckBox]@{
        Location = [Point]::new(440,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “桃”;
    }


    $chkPurple=[CheckBox]@{
        Location = [Point]::new(480,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “紫”;
    }
    
    $chkOrange=[CheckBox]@{
        Location = [Point]::new(520,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “橙”;
    }
    
    $chkYellow=[CheckBox]@{
        Location = [Point]::new(560,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “黄”;
    }
    
    $chkGreen=[CheckBox]@{
        Location = [Point]::new(600,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “緑”;
    }
    
    $chkLightBlue=[CheckBox]@{
        Location = [Point]::new(640,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “水”;
    }

    $chkBlue=[CheckBox]@{
        Location = [Point]::new(680,55);
        Size=[Size]::new(20,20);
        TextAlign = "MiddleLeft";
        AutoSize = $True;
        Checked = $True;
        Text = “青”;
    }

    $lblMember =[Label]@{
        Location = [Point]::new(728,53);
        Size=[Size]::new(40,20);
        Text = “担当”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtMember=[TextBox]@{
        Location = [Point]::new(771,53);
        Size=[Size]::new(105,20);
        Anchor="Top,Left";
        Text = “”;
    }

    $lblContents=[Label]@{
        Location = [Point]::new(5,76);
        Size=[Size]::new(80,20);
        Text = “対応内容”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtContents=[TextBox]@{
        Location = [Point]::new(88,76);
        Size=[Size]::new(180,20);
        Anchor="Top,Left";
        Text = “”;
    }
    $lblNote=[Label]@{
        Location = [Point]::new(272,76);
        Size=[Size]::new(70,20);
        Text = “備考”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtNote=[TextBox]@{
        Location = [Point]::new(345,76);
        Size=[Size]::new(140,20);
        Anchor="Top,Left";
        Text = “”;
    }
    $lblComment =[Label]@{
        Location = [Point]::new(490,76);
        Size=[Size]::new(70,20);
        Text = “履歴コメント”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }
    $txtComment=[TextBox]@{
        Location = [Point]::new(565,76);
        Size=[Size]::new(225,20);
        Anchor="Top,Left";
        Text = “”;
    }

    $btnSearch=[Button]@{
        Location = [Point]::new(830,75);
        Size=[Size]::new(90,24);
        Anchor="Top,Left";
        BackColor = "LightGray";
        Text = “検索(F5)”;
    }

    $lblResultTitle=[Label]@{
        Location = [Point]::new(5,100);
        Size=[Size]::new(924,20);
        Text = “◆検索結果一覧”; 
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left,Right";
        BorderStyle="FixedSingle";
        TextAlign = "MiddleLeft";
        AutoSize = $False;
    }


    #   ▼登録内容と履歴内容の区切り(TreeViewとその右側の区切り)
    $SpContainVertical=[SplitContainer]@{
        Location = [Point]::new(5,122);
        Size=[Size]::new(924,435);
        Anchor="Top,Left,Bottom,Right";
        Orientation = "Vertical";
        #BorderStyle = "FixedSingle";
    }

    $dgv = [DataGridView]@{
        Location = [Point]::new(5,122);
        Size=[Size]::new(624,435);
        Dock = "Fill";
        AutoGenerateColumns=$False;
        AllowUserToAddRows = $False;
        AllowUserToDeleteRows = $False;
        ReadOnly=$True;
        Anchor="Top,Left,Bottom,Right";
    }

    #   ▼変更履歴を表示するかどうかのチェックボックス
    $chkShowHistory=[CheckBox]@{
        Location = [Point]::new(160,102);
        Size=[Size]::new(140,17);
        BackColor = [System.Drawing.Color]::FromArgb(213, 219, 255);
        Anchor="Top,Left";
        Text = "変更履歴を表示"
        Checked=$true;
    }

    #   ▼変更履歴及びコメント一覧
    $dgvHistory = [DataGridView]@{
        Location = [Point]::new(632,122);
        Size=[Size]::new(300,435);
        Dock = "Fill";
        Anchor="Right,Bottom";
        AutoGenerateColumns=$false;
        AllowUserToAddRows=$False;
        AllowUserToDeleteRows=$False;
        ReadOnly=$True;
    }


    $grpFunction=[GroupBox]@{
        Location = [Point]::new(5,560);
        Size=[Size]::new(927,65);
        Anchor="Left,Bottom";
        Text = “”;
    }

    $lblF01 = [Label]@{
        Location = [Point]::new(29,8);
        Text = “F01”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF01 = [Button]@{
        Location = [Point]::new(5,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “参照”;
    }

    $lblF02 = [Label]@{
        Location = [Point]::new(104,8);
        Text = “F02”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF02 = [Button]@{
        Location = [Point]::new(80,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “編集”;
    }

    $lblF03 = [Label]@{
        Location = [Point]::new(178,8);
        Text = “F03”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF03 = [Button]@{
        Location = [Point]::new(155,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “”;
    }

    $lblF04 = [Label]@{
        Location = [Point]::new(252,8);
        Text = “F04”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF04 = [Button]@{
        Location = [Point]::new(230,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “検索(インデント)”;
    }

    $lblF05 = [Label]@{
        Location = [Point]::new(338,8);
        Text = “F05”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF05 = [Button]@{
        Location = [Point]::new(315,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “検索”;
    }
    
    $lblF06 = [Label]@{
        Location = [Point]::new(413,8);
        Text = “F06”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF06 = [Button]@{
        Location = [Point]::new(390,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “クリア”;
    }
        
    $lblF07 = [Label]@{
        Location = [Point]::new(488,8);
        Text = “F07”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF07 = [Button]@{
        Location = [Point]::new(465,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “”;
    }

    $lblF08 = [Label]@{
        Location = [Point]::new(562,8);
        Text = “F08”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF08 = [Button]@{
        Location = [Point]::new(540,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “”;
    }

    $lblF09 = [Label]@{
        Location = [Point]::new(648,8);
        Text = “F09”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF09 = [Button]@{
        Location = [Point]::new(625,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “復元”;
    }

    
    $lblF10 = [Label]@{
        Location = [Point]::new(723,8);
        Text = “F10”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF10 = [Button]@{
        Location = [Point]::new(700,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “”;
    }

    $lblF11 = [Label]@{
        Location = [Point]::new(798,8);
        Text = “F11”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }

    $btnF11 = [Button]@{
        Location = [Point]::new(775,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “”;
    }

    $lblF12 = [Label]@{
        Location = [Point]::new(873,8);
        Text = “F12”;
        BackColor = "Transparent";
        TextAlign = "MiddleCenter";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        AutoSize = $True;
    }


    $btnF12 = [Button]@{
        Location = [Point]::new(850,25);
        Size=[Size]::new(70,35);
        BackColor = "LightGray";
        Font = New-Object Drawing.Font("MS Gothic",9) ;
        Text = “閉じる”;
    }

    # ↑↑↑↑↑ Design End
    #endregion

    # コンストラクタ
    frm020_000_Search(){

        $this.Initialize();

        $frm_Load = {
            $this.SpContainVertical.SplitterDistance = 600;
        }
        $this.add_Load($frm_Load);

    }  

    # ------------------------------------------------------------------------------------------------------------
    # 初期化処理
    # ------------------------------------------------------------------------------------------------------------
    Initialize() {
        $this.Text = "検索画面"
        $this.Size = [Size]::new(950, 670);
        $this.Font = New-Object Drawing.Font("MS Gothic",10) ;
        $this.chkShowHistory.Font = New-Object Drawing.Font("MS Gothic",9) ;
        $this.dgv.Font = New-Object Drawing.Font("MS Gothic",9) ;
        $this.dgvHistory.Font = New-Object Drawing.Font("MS Gothic",9) ;
        $this.BackColor = [System.Drawing.Color]::FromArgb(232, 241, 255);
        
        #$this.Font = New-Object Drawing.Font("BIZ UDGothic",10) ;
        #$this.dgv.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
        #$this.chkShowHistory.Font = New-Object Drawing.Font("BIZ UDGothic",9) ;
        
        # ◆ コントロールの追加
        $this.Controls.Add($this.lblPatternTitle);
        $this.Controls.Add($this.lblFree);
        $this.Controls.Add($this.txtFree);
        $this.Controls.Add($this.lblTitle);
        $this.Controls.Add($this.txtTitle);
        $this.Controls.Add($this.lblStatus);
        $this.Controls.Add($this.chkTodo);
        $this.Controls.Add($this.chkDoing);
        $this.Controls.Add($this.chkDone);
        $this.Controls.Add($this.lblClass);
        $this.Controls.Add($this.txtClass);
        $this.Controls.Add($this.lblLimit);
        $this.Controls.Add($this.txtLimitStart);
        $this.Controls.Add($this.lblLimitBetween);
        $this.Controls.Add($this.txtLimitEnd);
        $this.Controls.Add($this.lblColoer);
        $this.Controls.Add($this.chkNoColor);
        $this.Controls.Add($this.chkRed);
        $this.Controls.Add($this.chkPink);
        $this.Controls.Add($this.chkPurple);
        $this.Controls.Add($this.chkOrange);
        $this.Controls.Add($this.chkYellow);
        $this.Controls.Add($this.chkGreen);
        $this.Controls.Add($this.chkLightBlue);
        $this.Controls.Add($this.chkBlue);
        $this.Controls.Add($this.lblMember);
        $this.Controls.Add($this.txtMember);
        $this.Controls.Add($this.lblContents);
        $this.Controls.Add($this.txtContents);
        $this.Controls.Add($this.lblNote);
        $this.Controls.Add($this.txtNote);
        $this.Controls.Add($this.lblComment);
        $this.Controls.Add($this.txtComment);
        $this.Controls.Add($this.btnSearch);

        #   グループボックスを作成(ファンクション)
        $this.grpFunction.Controls.add($this.lblF01)
        $this.grpFunction.Controls.add($this.btnF01)
        $this.grpFunction.Controls.add($this.lblF02)
        $this.grpFunction.Controls.add($this.btnF02)
        $this.grpFunction.Controls.add($this.lblF03)
        $this.grpFunction.Controls.add($this.btnF03)
        $this.grpFunction.Controls.add($this.lblF04)
        $this.grpFunction.Controls.add($this.btnF04)
        $this.grpFunction.Controls.add($this.lblF05)
        $this.grpFunction.Controls.add($this.btnF05)
        $this.grpFunction.Controls.add($this.lblF06)
        $this.grpFunction.Controls.add($this.btnF06)
        $this.grpFunction.Controls.add($this.lblF07)
        $this.grpFunction.Controls.add($this.btnF07)
        $this.grpFunction.Controls.add($this.lblF08)
        $this.grpFunction.Controls.add($this.btnF08)
        $this.grpFunction.Controls.add($this.lblF09)
        $this.grpFunction.Controls.add($this.btnF09)
        $this.grpFunction.Controls.add($this.lblF10)
        $this.grpFunction.Controls.add($this.btnF10)
        $this.grpFunction.Controls.add($this.lblF11)
        $this.grpFunction.Controls.add($this.btnF11)
        $this.grpFunction.Controls.add($this.lblF12)
        $this.grpFunction.Controls.add($this.btnF12)
        $this.Controls.add($this.grpFunction);

        #   検索結果一覧及び履歴一覧を追加する
        $this.Controls.Add($this.SpContainVertical);
        $this.Controls.Add($this.chkShowHistory);
        $this.SpContainVertical.Panel1.Controls.Add($this.dgv);
        $this.SpContainVertical.Panel2.Controls.Add($this.dgvHistory);
        $this.Controls.Add($this.lblResultTitle);

        # ◆ イベント関連
        #   履歴表示チェックボックス
        $chkShowHistory_CheckedChange={
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm();
            $form.dgvHistory.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
            foreach($dgvRow in $form.dgvHistory.Rows){
                if ($dgvRow.Cells[$script:DGV_HISTORY_COLNAME_KBN].Value -eq $script:PATTERN_CHANGELOG) {$dgvRow.Visible=$form.chkShowHistory.Checked;}
            }
        }
        $this.chkShowHistory.add_CheckedChanged($chkShowHistory_CheckedChange);
    
        #    検索ボタンのクリック処理を追加
        $btnSearch_Click = {
            $sender = $args[0];
            $e = $args[1];
            $form = $sender.FindForm()
            $form.btnF05_Click($sender,$e)
        }
        $this.btnSearch.add_Click($btnSearch_Click);

        ##   ファンクションキーボタンクリックイベント設定
        #    F01ボタン
        $btnF01Click={
            $sender = $args[0];
            $sender.FindForm().btnF01_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF01.add_Click($btnF01Click);
        #    F02ボタン
        $btnF02Click={
            $sender = $args[0];
            $sender.FindForm().btnF02_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF02.add_Click($btnF02Click);
        #    F03ボタン
        $btnF03Click={
            $sender = $args[0];
            $sender.FindForm().btnF03_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF03.add_Click($btnF03Click);
        #    F04ボタン
        $btnF04Click={
            $sender = $args[0];
            $sender.FindForm().btnF04_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF04.add_Click($btnF04Click);
        #    F05ボタン
        $btnF05Click={
            $sender = $args[0];
            $sender.FindForm().btnF05_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF05.add_Click($btnF05Click);
        #    F06ボタン
        $btnF06Click={
            $sender = $args[0];
            $sender.FindForm().btnF06_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF06.add_Click($btnF06Click);
        #    F07ボタン
        $btnF07Click={
            $sender = $args[0];
            $sender.FindForm().btnF07_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF07.add_Click($btnF07Click);
        #    F08ボタン
        $btnF08Click={
            $sender = $args[0];
            $sender.FindForm().btnF08_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF08.add_Click($btnF08Click);
        #    F09ボタン
        $btnF09Click={
            $sender = $args[0];
            $sender.FindForm().btnF09_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF09.add_Click($btnF09Click);
        #    F10ボタン
        $btnF10Click={
            $sender = $args[0];
            $sender.FindForm().btnF10_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF10.add_Click($btnF10Click);
        #    F11ボタン
        $btnF11Click={
            $sender = $args[0];
            $sender.FindForm().btnF11_Click($sender,$args[1]); # FindFormでボタンコントロールの所属するフォームを取得する
        }
        $this.btnF11.add_Click($btnF11Click);
        #    F12ボタン
        $btnF12Click={
            $sender = $args[0];
            $e = $args[1];
            $sender.FindForm().btnF12_Click($sender,$e);
        }
        $this.btnF12.add_Click($btnF12Click);

        #    履歴一覧の再建策
        $dgv_CurrentCellChanged = {
            $sender = $args[0];
            $e = $args[1];
            $form =$sender.FindForm();
            if ( $form.dgv -eq $null) { return;}
            if ( $form.dgv.CurrentRow -eq $null) { return;}
            if ( $form.dgv.DataSource -eq $null) { return;}
            
            $dt = New-Object System.Data.DataTable;
            $dt = $form.fdsCurrentSearchData.Tables[$script:DATA_TABLE_NAME_HISTORY].Clone();
            # 検索処理を実行
            $drFilterd = $form.fdsCurrentSearchData.Tables[$script:DATA_TABLE_NAME_HISTORY].Select(" " +  $script:COLNAME_HISTORY_ID + " = '" + $form.dgv.CurrentRow.Cells[$script:DGV_COLNAME_CONTENTS_ID].Value + "' ",  $script:COLNAME_HISTORY_HISTORYID + " ASC ");
            foreach ($drContent in $drFilterd){
                $dr = $dt.NewRow();
                $dr.ItemArray = $drContent.ItemArray;
                $dt.Rows.Add($dr);
            }
            $form.dgvHistory.DataSource = $dt;

            # 履歴一覧の表示日表示切替処理
            $form.dgvHistory.CurrentCell = $null; # Nullにしておかないと行を非表示にした時にエラー "現在のカレンシー マネージャーの位置に関連付けられた行を非表示にすることはできません。"が発生
            foreach($dgvRow in $form.dgvHistory.Rows){
                if ($dgvRow.Cells[$script:DGV_HISTORY_COLNAME_KBN].Value -eq $script:PATTERN_CHANGELOG) {$dgvRow.Visible=$form.chkShowHistory.Checked;}
            }
            
        }
        $this.dgv.add_CurrentCellChanged($dgv_CurrentCellChanged);

        # ファンクションキーを押下したときにイベントを発生
        $this.KeyPreview=$True;
        $KeyDownEvent={
                $sender = $args[0];
                $e = $args[1];
                #$PushKey = $_.KeyCode   $_ にもEventArgsが渡される
                # $PushKeyCode = $e.KeyCode
                # Function Key を押下した時の処理を実行する
                $this.RunFunctionKeyDownEvents($sender,$e);
                #If ( $PushKeyCode -eq "F1" )
                # {
                #     [System.Windows.Forms.MessageBox]::Show("押されたキーは:${PushKey}です", "結果")
                # } ElseIf ($PushKeyCode -eq "F12" ){
                #     $this.btnF12_Click($sender,$EventArg);
                # }
        }
        $this.add_KeyDown($KeyDownEvent);

        # 一覧を初期設定
        $this.DataGridViewInit();
    }

    # ------------------------------------------------------------------------------------------------------------
    # 画面上の値をクリアする
    # ------------------------------------------------------------------------------------------------------------
    ClearInit(){

        $this.txtFree.Text = "";
        $this.txtTitle.Text = "";
        $this.chkTodo.Checked = $True;
        $this.chkDoing.Checked = $True;
        $this.chkDone.Checked = $True;
        $this.txtClass.Text = "";
        $this.txtLimitStart.Text = "";
        $this.txtLimitEnd.Text = "";
        $this.chkNoColor.Checked = $True;
        $this.chkRed.Checked = $True;
        $this.chkPink.Checked = $True;
        $this.chkPurple.Checked = $True;
        $this.chkOrange.Checked = $True;
        $this.chkYellow.Checked = $True;
        $this.chkGreen.Checked = $True;
        $this.chkLightBlue.Checked = $True;
        $this.chkBlue.Checked = $True;
        $this.chkYellow.Checked = $True;
        $this.txtMember.Text = "";
        $this.txtContents.Text = "";
        $this.txtNote.Text = "";
        $this.txtComment.Text = "";
        
        $this.DataGridViewInit();
    }

    # ------------------------------------------------------------------------------------------------------------
    # Function Key 押下時イベント
    # ------------------------------------------------------------------------------------------------------------
    RunFunctionKeyDownEvents([object] $sender, [KeyEventArgs] $e){
        $PushKeyCode= $e.KeyCode;
        
        # ボタンが利用できない場合は処理しない
        if ($sender.Enabled -eq $false){return;}
        if ($sender.Text -eq "") {return;}

        If ( $PushKeyCode -eq "F1" ) {
            #[System.Windows.Forms.MessageBox]::Show("押されたキーは:${PushKeyCode}です", "結果")
            $this.btnF01.PerformClick();
        } ElseIf ($PushKeyCode -eq "F2" ){
            $this.btnF02.PerformClick();
        } ElseIf ($PushKeyCode -eq "F3" ){
            $this.btnF03.PerformClick();
        } ElseIf ($PushKeyCode -eq "F4" ){
            $this.btnF04.PerformClick();
        } ElseIf ($PushKeyCode -eq "F5" ){
            $this.btnF05.PerformClick();
        } ElseIf ($PushKeyCode -eq "F6" ){
            $this.btnF06.PerformClick();
        } ElseIf ($PushKeyCode -eq "F7" ){
            $this.btnF07.PerformClick();
        } ElseIf ($PushKeyCode -eq "F8" ){
            $this.btnF08.PerformClick();
        } ElseIf ($PushKeyCode -eq "F9" ){
            $this.btnF09.PerformClick();
        } ElseIf ($PushKeyCode -eq "F10" ){
            $this.btnF10.PerformClick();
        } ElseIf ($PushKeyCode -eq "F11" ){
            $this.btnF11.PerformClick();
        } ElseIf ($PushKeyCode -eq "F12" ){
            $this.btnF12.PerformClick();
        }
    }

    # ------------------------------------------------------------------------------------------------------------
    # F1 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF01_Click([object] $sender, [EventArgs] $e){
        $this.frmProject.SelectNodeById($this.GetIdFromPath($this.dgv.CurrentRow.Cells[$script:DGV_COLNAME_CONTENTS_ID].Value));
    }

    # ------------------------------------------------------------------------------------------------------------
    # F2 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF02_Click([object] $sender, [EventArgs] $e){
        $this.frmProject.SelectNodeById($this.GetIdFromPath($this.dgv.CurrentRow.Cells[$script:DGV_COLNAME_CONTENTS_ID].Value));
        $this.frmProject.Focus();
        $this.frmProject.txtTitle.Focus();
    }

    # ------------------------------------------------------------------------------------------------------------
    # F3 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF03_Click([object] $sender, [EventArgs] $e){

    }

    # ------------------------------------------------------------------------------------------------------------
    # F4 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF04_Click([object] $sender, [EventArgs] $e){
        $result = [System.Windows.Forms.MessageBox]::Show("インデント付きで結果を表示する場合は、検索条件を指定できません。検索条件がクリアされますがよろしいですか??", "確認", [System.Windows.Forms.MessageBoxButtons]::OKCancel, [System.Windows.Forms.MessageBoxIcon]::Question,[System.Windows.Forms.MessageBoxDefaultButton]::Button2)

        if ($result -eq [DialogResult]::OK){
            $this.ClearInit();
            $this.Syori_Search($true);
        }

    }

    # ------------------------------------------------------------------------------------------------------------
    # F5 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF05_Click([object] $sender, [EventArgs] $e){
        $this.Syori_Search($false);
    }

    # ------------------------------------------------------------------------------------------------------------
    # F6 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF06_Click([object] $sender, [EventArgs] $e){
        $this.ClearInit();
    }

    # ------------------------------------------------------------------------------------------------------------
    # F7 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF07_Click([object] $sender, [EventArgs] $e){

    }

    # ------------------------------------------------------------------------------------------------------------
    # F8 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF08_Click([object] $sender, [EventArgs] $e){

    }

    # ------------------------------------------------------------------------------------------------------------
    # F9 ボタンクリックイベント処理
    #  アーカイブされたタスクを復元する
    # ------------------------------------------------------------------------------------------------------------
    btnF09_Click([object] $sender, [EventArgs] $e){
        
        $form = $sender.FindForm();

        if ($form.dgv.CurrentRow -eq $null){return;}
        if ($form.dgv.CurrentRow.Cells[$script:DGV_COLNAME_CONTENTS_FILEPATTERN] -ne $script:FILEPATTERN_ARCHIVE) 
        {
            [System.Windows.Forms.MessageBox]::Show("アーカイブされたタスクを選択してください。", "エラー", [System.Windows.Forms.MessageBoxButtons]::OKOnly)
            return;
        }

        # TODO:アーカイブファイルが選択されているのチェック
        $result = [System.Windows.Forms.MessageBox]::Show("選択されたアーカイブファイルを復元してもよろしいですか?", "確認", [System.Windows.Forms.MessageBoxButtons]::OKCancel, [System.Windows.Forms.MessageBoxIcon]::Question,[System.Windows.Forms.MessageBoxDefaultButton]::Button2)

        if ($result -eq [DialogResult]::OK){
            $currentdDataRow = $form.dgv.CurrentRow.DataBoundItem;
            $fileInfo = New-Object System.IO.FileInfo($currentdDataRow[$script:COLNAME_CONTENTS_FILEPATH]);
            $strFileName = [System.IO.Path]::GetFileNameWithoutExtension($fileInfo.FullName);  # 静的メソッドの呼び出し
            $targetFilePath = $fileInfo.Directory.FullName + "\" + $form.GetIdFromPath($strFileName)+".zip";
            
            # ファイルパスを取得し、アーカイブファイルのIDからZIPファイルを取得(同階層の同じID.zipが存在するはず)
            # ZIPファイルを解凍し、解凍が完了したらZIPファイルとArchiveファイルを削除する
            Expand-Archive -Path $targetFilePath -DestinationPath $fileInfo.Directory.FullName
            
            # 圧縮したあとのファイルを削除する
            Remove-Item -Path $targetFilePath;
            Remove-Item -Path $fileInfo.FullName;            

        }

    }
    
    # ------------------------------------------------------------------------------------------------------------
    # F10 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF10_Click([object] $sender, [EventArgs] $e){

    }

    # ------------------------------------------------------------------------------------------------------------
    # F11 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF11_Click([object] $sender, [EventArgs] $e){

    }

    # ------------------------------------------------------------------------------------------------------------
    # F12 ボタンクリックイベント処理
    # ------------------------------------------------------------------------------------------------------------
    btnF12_Click([object] $sender, [EventArgs] $e){
        $this.Close()
    }

    # ------------------------------------------------------------------------------------------------------------
    # 検索処理
    # ------------------------------------------------------------------------------------------------------------
    Syori_Search([bool]$blnSetIndent){

        #$this.Enabled=$false;

        # フォルダ内のファイルを全て読み込む
        $this.fdsCurrentSearchData = New-Object System.Data.DataSet;
        $this.fdsCurrentSearchData = $this._ReadAllDataFile($blnSetIndent);

        $this.dgv.AutoSizeColumnsMode = [DataGridViewAutoSizeColumnsMode]::None;
        $this.dgv.AutoSizeRowsMode = [DataGridViewAutoSizeRowsMode]::None;
        $this.dgv.ColumnHeadersHeightSizeMode = [DataGridViewColumnHeadersHeightSizeMode]::DisableResizing;

        $dt = New-Object System.Data.DataTable;
        $dt = $this.fdsCurrentSearchData.Tables[$script:DATA_TABLE_NAME_CONTENT].Clone();

        $strWhere = "";
        $strTemp = "";
        # 検索条件を作成
        #   進捗状況
        $strTemp = "";
        if ($this.chkTodo.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:STATUS_TODO  + "'";
        }

        if ($this.chkDoing.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:STATUS_DOING  + "'";
        }
        if ($this.chkDone.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:STATUS_DONE  + "'";
        }
        if ($strWhere -ne "") { $strWhere +=" AND ";} 
        $strWhere+= " " + $script:COLNAME_CONTENTS_STATUS + " IN (" + $strTemp + ") ";
        
        #   色
        $strTemp = "";
        if ($this.chkNoColor.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "''";
        }
        if ($this.chkRed.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_RED  + "'";
        }
        if ($this.chkPink.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_PINK  + "'";
        }
        if ($this.chkPurple.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_PURPLE  + "'";
        }
        if ($this.chkOrange.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_ORANGE  + "'";
        }
        if ($this.chkYellow.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_YELLOW  + "'";
        }
        if ($this.chkGreen.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_GREEN  + "'";
        }
        if ($this.chkLightBlue.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_LIGHTBLUE  + "'";
        }
        if ($this.chkBlue.Checked -eq $true){ 
            if ($strTemp -ne "") { $strTemp +=",";} 
            $strTemp += "'" +  $script:LABELCOLOR_BLUE  + "'";
        }
        if ($strWhere -ne "") { $strWhere +=" AND ";} 
        $strWhere+= " " + $script:COLNAME_CONTENTS_COLORLABEL + " IN (" + $strTemp + ") ";

        # フリー検索
        if ($this.txtFree.Text -ne "") {
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_FOR_FREESEARCH + " LIKE '%" + $this.txtFree.Text + "%' "; 
        }
        # タイトル
        if ($this.txtTitle.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_TITLE + " LIKE '%" + $this.txtTitle.Text + "%' " 
        }
        # 分類
        if ($this.txtClass.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_CLASS + " = '" + $this.txtClass.Text + "' " 
        }
        # 期限(開始)
        if ($this.txtLimitStart.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " '" + $this.txtLimitStart.Text + "' <= "  + $script:COLNAME_CONTENTS_LIMITDAY ;
        }
        # 期限(終了)
        if ($this.txtLimitEnd.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_LIMITDAY + " <= '" + $this.txtLimitEnd.Text + "' " 
        }
        # 分類
        if ($this.txtMember.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_MEMBER + " = '" + $this.txtMember.Text + "' " 
        }
        # 対応内容
        if ($this.txtContents.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_CONTENTS + " LIKE '%" + $this.txtContents.Text + "%' " 
        }
        # 備考
        if ($this.txtNote.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_NOTE + " LIKE '%" + $this.txtNote.Text + "%' " 
        }
        # コメント
        if ($this.txtComment.Text -ne ""){ 
            if ($strWhere -ne ""){$strWhere +=" AND "; }
            $strWhere+= " " + $script:COLNAME_CONTENTS_FOR_COMMENTSSEARCH + " LIKE '%" + $this.txtComment.Text + "%' " 
        }

        # 検索処理を実行
        $drFilterd = $this.fdsCurrentSearchData.Tables[$script:DATA_TABLE_NAME_CONTENT].Select($strWhere, $script:COLNAME_CONTENTS_FOR_SORT + " ASC ," + $script:COLNAME_CONTENTS_FOR_SORTSUB + " ASC ");
        foreach ($drContent in $drFilterd){
            $dr = $dt.NewRow();
            $dr.ItemArray = $drContent.ItemArray;
            $dt.Rows.Add($dr);
        }
        $this.dgv.DataSource = $dt;

        # わかりやすいようにするために「色」に合わせてDataGridViewの列の色を変える
        foreach ($dgvRow in $this.dgv.Rows){
            if ($dgvRow.Cells[$script:DGV_COLNAME_CONTENTS_COLORLABEL].Value -ne "") {
                $dgvRow.Cells[$script:DGV_COLNAME_CONTENTS_COLOR].Style.BackColor = $this.frmProject._GetColor($dgvRow.Cells[$script:DGV_COLNAME_CONTENTS_COLORLABEL].Value);
            }
        }

        $this.dgvHistory.AutoSizeColumnsMode = [DataGridViewAutoSizeColumnsMode]::None;
        $this.dgvHistory.AutoSizeRowsMode = [DataGridViewAutoSizeRowsMode]::None;
        $this.dgvHistory.ColumnHeadersHeightSizeMode = [DataGridViewColumnHeadersHeightSizeMode]::DisableResizing;
        $this.dgvHistory.DataSource = $null;  # 履歴データはdgvのCurrentCellChangedのイベント内で処理する

        # インデント検索をする場合は並び替えができると階層がおかしくなるのでできないようにする
        foreach ($column in $this.dgv.Columns) {
            if($blnSetIndent -eq $true) { $column.SortMode = "NotSortable";}
            else { $column.SortMode = "Automatic";}
        }

        # $this.dgv.AutoSizeColumnsMode = [DataGridViewAutoSizeColumnsMode]::AllCells;
        # $this.dgv.AutoSizeRowsMode = [DataGridViewAutoSizeRowsMode]::AllCells;
        # $this.dgv.ColumnHeadersHeightSizeMode = [DataGridViewColumnHeadersHeightSizeMode]::AutoSize;

        $this.Enabled=$true;
    }

        
    # ------------------------------------------------------------------------------------------------------------
    # Dataフォルダは以下に存在するTask.xmlとTaskArchive_***.xmlファイルをすべ著見込んでDataSetとして返す
    # ------------------------------------------------------------------------------------------------------------
    [System.Data.DataSet]_ReadAllDataFile([bool]$blnSetIndent){
        
        # フォルダパスをすべて取得し、並び替えを行う
        $directrys = [System.IO.Directory]::GetDirectories($this.GetDataFolderPath(), "*", [System.IO.SearchOption]::AllDirectories);
        $directrys = $directrys | Sort-Object ;
        $lstDirectorys = [System.Collections.Generic.List[string]]::new();
        $lstDirectorys.Add($this.GetDataFolderPath());
        foreach($p in $directrys){$lstDirectorys.Add($p);}

        $dsReturn = New-Object System.Data.DataSet;

        # コンテンツテーブル作成
        $dtContents = New-Object System.Data.DataTable;
        $dtContents.TableName = $script:DATA_TABLE_NAME_CONTENT;
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_ID,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FILEPATH,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_TITLE,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_LIMITDAY,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_STATUS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_COLORLABEL,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_MEMBER,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CLASS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CREATEIONDATETIME,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_CONTENTS,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_NOTE,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FOR_FREESEARCH,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FOR_COMMENTSSEARCH,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FOR_SORT,[int]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FOR_SORTSUB,[int]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_FOR_FILEPATTERN,[string]);
        $dtContents.Columns.Add($script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH,[string]);
        
        # 履歴テーブル作成
        $dtHistorys = New-Object System.Data.DataTable;
        $dtHistorys.TableName = $script:DATA_TABLE_NAME_HISTORY;
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_ID,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_HISTORYID,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_CREATEIONDATETIME,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_CONTROL,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_PATTERN,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_USERNAME,[string]);
        $dtHistorys.Columns.Add($script:COLNAME_HISTORY_HISTORYCONTENTS,[string]);

        $intSortNo = 1;
        $intSortSubNo = 1;
        foreach ($path in $lstDirectorys){

            $dicInfo = New-Object System.IO.DirectoryInfo($path);
            $dsTemp = New-Object System.Data.DataSet;
            $strTaskFilePath = $dicInfo.FullName+ "\" + $script:DATA_FILE_NAME;
            # ◆タスクの情報を読み込み(Task.xml)
            if ((Test-Path $strTaskFilePath) -eq $true) {
                $dsTemp.ReadXml($strTaskFilePath);
                #  コンテンツのデータを取込
                $dr = $dtContents.NewRow();
                $dr[$script:COLNAME_CONTENTS_FILEPATH] = $dicInfo.FullName;
                $dr[$script:COLNAME_CONTENTS_FOR_SORT] = $intSortNo;
                $dr[$script:COLNAME_CONTENTS_FOR_SORTSUB] = $intSortSubNo;
                $dr[$script:COLNAME_CONTENTS_FOR_FILEPATTERN] = $script:FILEPATTERN_TASK;
                $intSortNo += 1;
                foreach ($col in $dsTemp.Tables[$script:DATA_TABLE_NAME_CONTENT].Columns){
                    $dr[$col.ColumnName] = $dsTemp.Tables[$script:DATA_TABLE_NAME_CONTENT].Rows[0][$col.ColumnName];
                }
                
                #  階層がわかるようにスペース埋めする
                if ($blnSetIndent -eq $true){
                    $indent = $this.CountChar($path.Replace($this.GetDataFolderPath(),""),"\") - 1;
                    $strSpace = "";
                    for ($i = 0; $i -lt $indent; $i++) {
                        $strSpace += " ";    
                    }
                    $dr[$script:COLNAME_CONTENTS_TITLE] = $strSpace + $dr[$script:COLNAME_CONTENTS_TITLE];
                }
                
                #  履歴データデータ
                $strCommentSearch = "";
                for ($i = 0; $i -lt $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows.Count; $i++) {
                    $drHistory = $dtHistorys.NewRow();
                    foreach ($col in $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Columns){
                        $drHistory[$col.ColumnName] = $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows[$i][$col.ColumnName];
                    }
                    $dtHistorys.Rows.Add($drHistory);
                    
                    # 検索用のコメントを作成する
                    if ($dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows[$i][$script:COLNAME_HISTORY_PATTERN] -eq "コメント") {
                        $strCommentSearch += $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Rows[$i][$script:COLNAME_HISTORY_HISTORYCONTENTS] + "     "
                    }
                }

                #  検索用の項目
                $dr[$script:COLNAME_CONTENTS_FOR_FREESEARCH] = $dr[$script:COLNAME_CONTENTS_TITLE] + "     " + $dr[$script:COLNAME_CONTENTS_CONTENTS] + "     " + $dr[$script:COLNAME_CONTENTS_NOTE] + + "     " + $dr[$script:COLNAME_CONTENTS_MEMBER] + "     " + $dr[$script:COLNAME_CONTENTS_CLASS] + "     " + $strCommentSearch;
                $dr[$script:COLNAME_CONTENTS_FOR_COMMENTSSEARCH] = $strCommentSearch;
                $dtContents.Rows.Add($dr);
            }

            # ◆アーカイブの情報を読み込み(TaskArchive_[ID].xml)
            $archiveFiles = $dicInfo.GetFiles($script:DATA_ARCHIVE_FILE_NAME + "*",[System.IO.SearchOption]::TopDirectoryOnly)
            foreach ($fileInfo in $archiveFiles) {
                $dsTemp = New-Object System.Data.DataSet;
                $dsTemp.ReadXml($fileInfo.FullName);
                
                foreach ($drTemp in $dsTemp.Tables[$script:DATA_TABLE_NAME_CONTENT].Rows) {
                    $dr = $dtContents.NewRow();
                    $dr[$script:COLNAME_CONTENTS_FILEPATH] = $fileInfo.FullName;
                    $dr[$script:COLNAME_CONTENTS_FOR_SORT] = $intSortNo;
                    $dr[$script:COLNAME_CONTENTS_FOR_SORTSUB] = $intSortSubNo;
                    $dr[$script:COLNAME_CONTENTS_FOR_FILEPATTERN] = $script:FILEPATTERN_ARCHIVE;

                    $intSortSubNo += 1;   # 並び替え用の区分。ファイルの並び替えは"圧縮"処理の時に並び替えてから保存しているので行の順番を記録しておけばよい。
                    foreach ($col in $dsTemp.Tables[$script:DATA_TABLE_NAME_CONTENT].Columns){
                        $dr[$col.ColumnName] = $drTemp[$col.ColumnName];
                    }

                    #  階層がわかるようにスペース埋めする
                    if ($blnSetIndent -eq $true){
                        $strArchivedFilePath = $path + "\" + $drTemp[$script:COLNAME_CONTENTS_OPTIONS_ONLY_ARCHIVE_RELATIVEPATH]; # アーカイブされていなかったとしたときのフォルダパス
                        $indent = $this.CountChar($strArchivedFilePath.Replace($this.GetDataFolderPath(),""),"\") - 1;

                        $strSpace = "";
                        for ($i = 0; $i -lt $indent; $i++) {
                            $strSpace += " ";    
                        }
                        $dr[$script:COLNAME_CONTENTS_TITLE] = $strSpace + $dr[$script:COLNAME_CONTENTS_TITLE];
                    }
                    
                    $strCommentSearch = "";
                    $drSelHistory = $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Select($script:COLNAME_HISTORY_ID + " = '" + $drTemp[$script:COLNAME_CONTENTS_ID] + "'","");
                    for ($i = 0; $i -lt $drSelHistory.Length; $i++) {
                        $drHistory = $dtHistorys.NewRow();
                        foreach ($col in $dsTemp.Tables[$script:DATA_TABLE_NAME_HISTORY].Columns){
                            $drHistory[$col.ColumnName] = $drSelHistory[$col.ColumnName];
                        }
                        $dtHistorys.Rows.Add($drHistory);
                        
                        # 検索用のコメントを作成する
                        if ($drSelHistory[$i][$script:COLNAME_HISTORY_PATTERN] -eq "コメント") {
                            $strCommentSearch += $[$i][$script:COLNAME_HISTORY_HISTORYCONTENTS] + "     "
                        }
                    }
                    #  検索用の項目
                    $dr[$script:COLNAME_CONTENTS_FOR_FREESEARCH] = $dr[$script:COLNAME_CONTENTS_TITLE] + "     " + $dr[$script:COLNAME_CONTENTS_CONTENTS] + "     " + $dr[$script:COLNAME_CONTENTS_NOTE] + + "     " + $dr[$script:COLNAME_CONTENTS_MEMBER] + "     " + $dr[$script:COLNAME_CONTENTS_CLASS] + "     " + $strCommentSearch;
                    $dr[$script:COLNAME_CONTENTS_FOR_COMMENTSSEARCH] = $strCommentSearch;
                    $dtContents.Rows.Add($dr);

                }
            }
        }

        $dsReturn.Tables.Add($dtContents);
        $dsReturn.Tables.Add($dtHistorys);

        return $dsReturn;

    }

    # ------------------------------------------------------------------------------------------------------------
    # 検索結果をインデント付きで設定するために必要
    # ------------------------------------------------------------------------------------------------------------
    [int]CountChar([string]$strWord,[string]$strChar){
        return $strWord.Length - $strWord.Replace($strChar,"").Length;
    }

    # ------------------------------------------------------------------------------------------------------------
    # DataGridViewの初期設定を実施
    # ------------------------------------------------------------------------------------------------------------
    DataGridViewInit(){
        
        $this.dgv.RowTemplate.Height = 20;
        $this.dgv.AlternatingRowsDefaultCellStyle.BackColor = "LightYellow"

        $this.dgv.Columns.Clear();
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_COLOR,"",20,$script:DGV_ALIGN_MIDDLELEFT,"");
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_FILEPATTERN,"状態",50,$script:DGV_ALIGN_MIDDLECENTer,$script:COLNAME_CONTENTS_FOR_FILEPATTERN);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_TITLE,"タイトル",140,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_TITLE);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_LIMITDAY,"期限",75,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_LIMITDAY);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_LIMITALERTDAYCOUNT,"通知前",55,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_LIMITALERTDAYCOUNT);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_STATUS,"進捗状況",65,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_STATUS);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_COLORLABEL,"色",30,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_COLORLABEL);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_MEMBER,"担当",80,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_MEMBER);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_CLASS,"分類",80,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_CLASS);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_CONTENTS,"対応内容",120,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_CONTENTS);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_NOTE,"備考",120,$script:DGV_ALIGN_MIDDLELEFT,$script:COLNAME_CONTENTS_NOTE);
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_CREATEIONDATETIME,"登録日時",160,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_CREATEIONDATETIME);
        $this.dgv.Columns.Add($dc)

        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_ID,"ID",120,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_ID);
        # $dc.Visible = $False
        $this.dgv.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_COLNAME_CONTENTS_FILEPATH,"ファイルパス",0,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_CONTENTS_FILEPATH);
        $dc.Visible = $False
        $this.dgv.Columns.Add($dc)
        $this.dgv.DataSource = $null;

        $this.dgvHistory.RowTemplate.Height = 20;
        $this.dgvHistory.AlternatingRowsDefaultCellStyle.BackColor = "LightYellow"

        $this.dgvHistory.Columns.Clear();
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_KBN,"区分",50,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_PATTERN);
        $this.dgvHistory.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_CONTROL,"コントロール",70,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_CONTROL);
        $this.dgvHistory.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_HOSTNAME,"PC名",70,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_USERNAME);
        $this.dgvHistory.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_CONTENTS,"内容",120,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_HISTORYCONTENTS);
        $this.dgvHistory.Columns.Add($dc)

        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_TRKDATETIME,"登録日時",140,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_CREATEIONDATETIME);
        $this.dgvHistory.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_ID,"ID",120,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_ID);
        $dc.Visible = $False
        $this.dgvHistory.Columns.Add($dc)
        $dc = $this.GetDataGridColumnText($script:DGV_HISTORY_COLNAME_HISTORYID,"履歴ID",120,$script:DGV_ALIGN_MIDDLECENTER,$script:COLNAME_HISTORY_HISTORYID);
        $dc.Visible = $False
        $this.dgvHistory.Columns.Add($dc)

        $this.dgvHistory.DataSource = $null;

    }

    # ------------------------------------------------------------------------------------------------------------
    # DataGridViewのColumnを取得する
    # ------------------------------------------------------------------------------------------------------------
    [DataGridViewTextBoxColumn]GetDataGridColumnText([string] $strName,[string]$strHeaderText,[int]$intWidth,[string]$strCellTextAligment,[string]$strDataPropName) {
        $dc = New-Object DataGridViewTextBoxColumn ;
        $dc.Name = $strName;
        $dc.HeaderText = $strHeaderText;
        $dc.Width = $intWidth;
        $dc.DefaultCellStyle.Alignment = $strCellTextAligment;
        $dc.HeaderCell.Style.Alignment = "MiddleCenter";
        $dc.ReadOnly=$True;
        $dc.AutoSizeMode = "NotSet"      # 処理速度向上
        #$dc.SortMode = "NotSortable";    # 並び替えを行わないようにすることでヘッダのテキストを中央寄せにできる
        $dc.DataPropertyName = $strDataPropName;
        return $dc;
    }


    # ------------------------------------------------------------------------------------------------------------
    # パスからタスクのIDを取得する(yyyyMMddHHmmssがID)
    # ------------------------------------------------------------------------------------------------------------
    [string] GetIdFromPath([string]$strFolderPath){
        return $strFolderPath.Substring($strFolderPath.Length - 17,17);
    }

    # ------------------------------------------------------------------------------------------------------------
    # データを保存しているフォルダを取得する
    # ------------------------------------------------------------------------------------------------------------
    [string] GetDataFolderPath(){
        return  ($this.fstrCurrentPath + "\Data");
    }
}

#   呼び出し用のMain.ps1は別途作成する必要がある
# Debug用 デバッグする際にはコメントアウトを削除し、VisualStudioCodeなどでF5。事前に「Add-Type -AssemblyName System.Windows.Forms;」「Add-Type -AssemblyName System.Windows.Forms;」の実行が必要
[Application]::EnableVisualStyles();
#$form = [frm010_000_Projet]::new();
#$form = [frm020_000_Search]::new();
#$form.fstrCurrentPath = $CurrentDir; # インスタンス化してから、スクリプト上で設定しないと、クラスの中ではMyInvocationが取得できない。
#$form.StartPosition="CenterScreen";   # 列挙体は文字列で指定する必要がある
#$form.ShowDialog();







PowerShellでEdgeを自動化(インストール不要。参考:郵便追跡サービス自動操作)

1.経緯について  RPAのソフトをインストールできないので、これまでVBSでCreateObjectでブラウザの自動操作をすることがたまにあった。 ※いざというときの手札として持っているだけで安心感が段違い  見た目上IEがインストールされていなくても、CreateObject...