【PowerShell】フォルダパスを取得する関数(GUI/CLI両対応)

# 概要
Powershell上で指定したフォルダのパスを返す自作関数の紹介。
単体での利用ではなく、他のスクリプトなどの処理から呼び出すことを前提としている。
フォルダ選択ダイアログを使ったフォルダパス取得にも対応。

## ユースケース
ツールなどで特定のフォルダを指定する必要が有る際に呼び出す。
主にインタラクティブなCLIツールとして使用可能。

# 関数紹介
関数名：Select-Dir

## 機能要件
- 任意のフォルダのフルパスを返す
- インタラクティブな処理を可能にする
- ダイアログボックスを使用したGUIでのインタラクティブな処理を盛り込む。
- 指定パスが存在するか判定処理をいれる
- 指定パスがディレクトリであるか判定処理をいれる

## ソースコード
```powershell:Select-Dir.psm1
###################
#フォルダパス取得関数
###################
function Select-Dir(){
###################
#<概要>
#指定したフォルダパスを呼び出し元に返します。
#<書式>
#Select-Dir [-cliDialog | -guiDialog] [-Path <string>]
###################
    Param(
        #オプションの規定値はCLIでのダイアログ表示
        [switch]$cliDialog = $true, #cliDialogのブール値は処理には使わない。デフォルトの動作をわかりやすくするためにあえて記述している。
        [switch]$guiDialog,
        [string]$Path =""
    )

###############
#guiDialogの処理
###############
    if($guiDialog){
        #フォルダ選択オブジェクトの設定
        Add-Type -AssemblyName System.Windows.Forms
        $dialog = New-object System.Windows.Forms.FolderBrowserDialog -Property @{
            Description = "フォルダを選択してください。"
        }

        if($dialog.ShowDialog() -eq "OK") {
            $Selected_Path = $dialog.SelectedPath
            Write-Host "${Selected_Path}が選択されました。"
            return $Selected_Path
        }else{
            Write-Host "フォルダは選択されませんでした。"
            return
        }
    }

###############
#cliDialogの処理
###############
    #引数にパスが指定されているか判定
    if($Path -eq ""){
        $Selected_Path = Read-Host "対象ディレクトリのパスを入力してください。"
        $Selected_Path = $Selected_Path -replace '^"|"$' -replace "^'|'$"
        if($Selected_Path -eq ""){#Read-Hostは何も入力しなかった場合に空文字列が返される(nullじゃない点に注意)
            Write-Host "パスが未指定のため処理を終了します。"
            return
        }
    }else{
        $Selected_Path = $Path
    }

    #対象フォルダの存在確認
    $bool = Test-Path -Path $Selected_Path -PathType Container
    if(! $bool){
       Write-Host "対象パスのオブジェクトはディレクトリではありません。"
       throw "'${Selected_Path}' is not Directory"
    }
    
    return $Selected_Path
}
```

### 書式
```powershell:書式
Select-Dir [-cliDialog | -guiDialog] [-Path <string>]
```

### オプション説明
| オプション名 | 説明                                                                                 | 
| :----------- | :----------------------------------------------------------------------------------- | 
| -cliDialog   | コンソールからパスの入力促す<br>既定でON                                             | 
| -guiDialog   | フォルダ選択ダイアログから対象フォルダを選択する                                     | 
| -Path        | 任意のフォルダパスを指定する<br>主にパスの存在有無、フォルダ判定などの際に呼び出す。 | 

### 解説
オプションを切り替えることによって、GUIダイアログからのフォルダ選択、コンソール上に直接入力も可能。

例)-guidialogオプション指定時
<img width="400" alt="フォルダ選択ダイアログ" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3292417/77116c89-1309-ede4-7d45-699c640b81a1.png">

例)-cliDialogオプション指定時
```powershell:-cliDialog
PS C:\> Select-Dir -cliDialog
対象ディレクトリのパスを入力してください:
```

### 備忘
- Read-Hostコマンドレットは未入力でEnterを押した場合、返す値はnullではなく、空文字("")である。
- パスのディレクトリ判定を行う場合、gciとPSIscontainerを使うよりも、Test-Pathのが簡単。というのは、gciにフォルダのパスを渡すとそのフォルダ配下の内容が返るため、一つ上の階層から走査する必要があるため。

またオプション"-Path"は、オプションを指定せずにパラメータを渡せる。
```powershell:-Path未指定で実行
Select-Dir [フォルダパス]
```

オプションを明示しない場合、Powershellの規定で位置指定パラメータとして解釈される。
Paramブロック内には、3つの値が定義されているが、
内2つはSwitchパラメータのため無視される模様。
結果、関数に渡されたパラメータは「Path」へと代入される。

## 修正履歴
更新日：2023/11/9
Read-Hostコマンドに入力するパスにクォーテーションが含まれている場合に、
ディレクトリ判定処理でfalseとなりthrowされる問題を修正しました。

# 参考
https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.folderbrowserdialog?view=windowsdesktop-7.0