関数定義について

VisualStudioCodeやPowerShellISEでデバッグしているから気が付かなかったが、
関数の定義は「実行部分より前に定義」しなくてはならない。

これに気が付かなかったというか「動いているじゃん」という状況だったのだが、
PowerShelllのコンソールを走らせていると、
前回定義した関数定義がそのまま残っており、
それを再利用している形になっていた。

そのためにps1のスクリプトを動かしていても気が付かず、
関数に加えた変更が反映されず、1,2分後に再度動かすと反映されるという現象に見舞われることになってしまっていた。

orz


以下の様に関数定義部分を別ファイルに分けて対応

functions.ps1

#アプリケーションデータフォルダ初期化処理
function init_app_dir ($app_name) {
    #APPDATAの特殊ファイルを取得する
    $path_app_data = (get-ChildItem env: | Where-Object {$_.Name -eq "APPDATA"} | Select-Object Value).Value;

    #特殊フォルダのパスを確認
    if((Test-Path -Path $path_app_data -PathType Container) -eq $FALSE){
        # メッセージボックスの表示
        [System.Windows.Forms.MessageBox]::Show("特殊フォルダ" + $path_app_data + "が存在しないかアクセスできません", "致命的なエラー")
        exit 1
    }

    #データ保存先パス変数を生成
    $mypath = ($path_app_data + '\' + $app_name)

    #このスクリプトのためのフォルダがあるかどうかを判断。
    #無ければ作る
    if((Test-Path -Path $mypath -PathType Container) -eq $FALSE)
    {
        #アプリケーションデータの保存先フォルダを作成する
        #処理的にはIOを伴うのでtry-catchを入れる
        try{
            #フォルダを作る処理
            New-Item -Path $mypath -ItemType Directory
        }catch [Exception] {
            #タイミング的に作られていたら気にせず進む。
            #無ければ何らかのエラーなので、エラーメッセージを表示して終了
            if((Test-Path -Path $mypath -PathType Container) -eq $FALSE){
                # メッセージボックスの表示
                [System.Windows.Forms.MessageBox]::Show(
                        "アプリケーションデータ保存用フォルダ:" + 
                        $mypath + 
                        "の作成に失敗しました(" + 
                        $error +
                        ")", 
                        "致命的なエラー"
                )
                exit 1          
            }
        }
    }

    return $mypath
}

#保存データの初期化を行う
function initSaveData($path_app_data)
{
    #基本の保存データはハッシュテーブルで。
    #データ形式が変わっても良いように基本はここで定義する
    #この基本にファイルへと保存したデータから読み込ませて代入する
    #新しいデータ形式になっても、足りないデータ分は新しいデータの初期値となるので、
    #保存時にはデータは最新に書き換わるし、エラーとなることもない。

    $initial_data = @{
        SelectedData = @{
            ConnectionType = "ODBC";
            ConnectionString = ""
        }
    }

    #データの読み込み
    #読込むデータが無ければ新規作成保存
    $path_data_file = $path_app_data + "\save_data.txt"

    if((Test-Path -Path $path_data_file -PathType Leaf) -eq $False)
    {
        #新規保存
        $save_data = ($initial_data | ConvertTo-Json)
        $save_data | Out-File -FilePath $path_data_file
    }

    return $save_data
}

#データベース接続文字列を形成するフォームオブジェクトの作成と実行
function showDBConnectionDialog ($app_path, [ref]$cs) {
    #フォームの生成
    $form = New-Object System.Windows.Forms.Form
    $form.Text = "データベース接続文字列 生成"
    $form.Size = New-Object System.Drawing.Size(260, 360)
    #しょっちゅう裏に隠れるのでTOPMOSTで最前面に
    $form.TopMost = $true

    #ラベルの生成
    $labelEntry = New-Object System.Windows.Forms.Label
    $labelEntry.Location = New-Object System.Drawing.Point(10,10)
    $labelEntry.Size = New-Object System.Drawing.Size(230, 20)
    $labelEntry.Text = "接続するデータベースの種類を選んでください"

    #リストボックスの生成
    $lbCT = New-Object System.Windows.Forms.ListBox
    $lbCT.Location = New-Object System.Drawing.Point(10, 30)
    $lbCT.Size = New-Object System.Drawing.Size(210, 50)

    #ラベル接続文字列の生成
    $lblCS = New-Object System.Windows.Forms.Label
    $lblCS.Location = New-Object System.Drawing.Point(10, 80)
    $lblCS.Size = New-Object System.Drawing.Size(210,20)
    $lblCS.Text = "接続文字列:"


    #テキストボックスの生成
    $tbCS = New-Object System.Windows.Forms.TextBox
    $tbCs.Location = New-Object System.Drawing.Point(10, 100)
    $tbCs.Size = New-Object System.Drawing.Size(210, 20)


    [void]$lbCT.Items.Add("ODBC")
    [void]$lbCT.Items.Add("Npgsql")
    [void]$lbCT.Items.Add("")


    #イベントの登録
    $form.Add_Load($onloadevent)
    

    #ラベルのフォームへの登録
    $form.Controls.Add($labelEntry)
    #リストボックスのフォームへの登録
    $form.Controls.Add($lbCt)
    #ラベル接続文字列のフォームへの登録
    $form.Controls.Add($lblCs)
    #テキストボックスのフォームへの登録
    $form.Controls.Add($tbCS)


    #ダイアログとして実行
    #多分ダイアログじゃなくても良いが、今はダイアログで。イベント管理が大変そうなので。
    #といってもJavascriptレベルなので、そこまででもないが
    $result = $form.showDialog()

    if($result -eq "OK")
    {


    }
}

$onloadevent = {
    [System.Windows.Forms.MessageBox]::Show("テスト22", "致命的なエラー")
}


main.ps1

#関数部分読み出し
./functions.ps1

#設定
#Applicationとしての名称(英字)
$app_name_en = "DbTableSearch"

# アセンブリの読み込み
Add-Type -Assembly System.Windows.Forms
Add-Type -AssemblyName System.Drawing

#フォームなどがデフォルトがUS-ASCIIで化けるため、SJISに変更する
$OutputEncoding = [console]::OutputEncoding
#アプリケーションデータ保存フォルダ
$path_my_app_data = ""
#データベースへの接続用文字列
[string]$db_connection_strings = ""


#アプリケーション保存先ディレクトリ用初期化処理
$path_my_app_data = init_app_dir $app_name_en

#保存ファイルより設定の読み込み
$save_data = initSaveData $path_my_app_data

$save_data

#データベース接続文字を形成する関数の呼び出し
showDBConnectionDialog $path_my_app_data ([ref]$db_connection_strings)