PowerShell で Yes/No プロンプトをクリーンアップする方法

PowerShell で Yes/No プロンプトをクリーンアップする方法

そこで、仕事で使いたい「自動化」スクリプトをもらいました。でも、私は文字通り Powershell で何も書いたことがなかったので、当然ながら最初から全部書き直しました。ひどい出来だったからです (私の方がずっと良いというわけではありませんが)。でも、Powershell を 5 日間使ってみて、かなり進歩したと思います。でも、私の yes/no プロンプトはかなり乱雑になってしまったので、ここで実際に何をしているのかわかっている人が私に何かヒントをくれるといいのですが。それで、これが私のコードです。

これらは即時の宣言です...

    $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&yes"
    $no = New-Object System.Management.Automation.Host.ChoiceDescription "&no"
    $help = New-Object System.Management.Automation.Host.ChoiceDescription "&help"
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no, $help)


These are part of the checks for the Datacenter portion. (The whole script block is Datacenters, Clusters, Hosts utilizing VMware PowerCLI.)

    While ($ChoiceTask -eq "Check Datacenters"){
        Clear-Host
        Write-Output "Would you like to create any Datacenters?"
            $result = $host.ui.PromptForChoice($title, $message, $options, 0)
                switch($result){
                    0{$ChoiceTask = "Datacenters"
                    $MadeDatacenters = $true}
                    1{$ChoiceTask = "Check Clusters"
                    $MadeDatacenters = $false}
                    2{
                Write-Output "A virtual datacenter is a container for all the inventory objects required to
    complete a fully functional environment for operating virtual machines.
    Recommended procedure is creating three datacenters. The UCS Datacenter, the vSAN
    Datacenter, and the Witness Datacenter. However, you may change this to fit your needs."
                Read-Host -Prompt "(Press 'Enter' to continue)"
                    }
                }
    }

    #Creates appropriate amount of Datacenters for User

    While ($ChoiceTask -eq "Datacenters"){
        Clear-Host
        $DataCenterAmount = ([String] $DataCenterAmount = (Read-Host "How many datacenters would you like to create?"))
        Clear-Host
        Write-Color -Text "You want to create ","$DataCenterAmount ","Datacenters. Is this correct?" -Color White,Yellow,White
        $result = $host.ui.PromptForChoice($title, $message, $options, 1)
            switch ($result){
                0{
                    Clear-Host
                    [System.Collections.ArrayList]$DatacenterArray = @()
                    $Curr = 1
                    While ($Curr -le $DataCenterAmount){ #Processes amount of datacenters to be created.
                        Write-Color -Text "Please enter the name of Datacenter ","$Curr",":" -Color White,Yellow,White
                        $DatacenterName = Read-Host
                        Clear-Host
                        Write-Color -Text "The name of Datacenter"," $Curr"," is"," $DatacenterName",". Is this correct?" -Color White,Yellow,White,Yellow,White
                        $result = $host.ui.PromptForChoice($title, $message, $options, 1)
                            switch ($result){
                                0{ #After confirmation of Datacenter name - creates datacenter
                                $folder = Get-Folder -NoRecursion
                                try {
                                New-Datacenter -Name $DatacenterName -Location $folder
                                }
                                catch{
                                    Clear-Host
                                    Write-Color -text "[WARNING] An error has occured during the Datacenter creation process, a connection error may have ocurred." -color red
                                    Read-Host "(Press 'Enter' to continue:)"
                                    $ChoiceTask = "Standard Check"
                                }
                                $DatacenterArray.Add($DatacenterName)
                                Clear-Host
                                Write-Color -Text "Datacenter"," $DatacenterName"," successfully created! (Press 'Enter' to continue)" -Color White,Yellow,White
                                Read-Host
                                $Curr++
                                Clear-Host
                                }
                                1{}
                            }
                    }
                $ChoiceTask = "Check Clusters"
                }#End 'Yes' Selection
                1{}
            }
    }

ご覧のとおり、非常に面倒です。しかし、ユーザーが選択が正しいことを確認することが重要です。私の知る限り、これは yes/no プロンプトの最良の方法ですが、自分のためにこれを本当に整理したいと思います。上記を見逃した場合、これは VMware の PowerCLI と連携しているため、一部のアクションがわからない場合はそれが理由です。また、write-color は、画面に印刷される変数の色付けを簡素化するためのカスタム関数です。ただし、これを行うにはもっと簡単な方法もあると思います。

答え1

使用スプラッティング読みやすさを向上させるために長い/大きなパラメータセットを渡すには:

$splat = @{
  'Text' = ('The name of Datacenter ', $Curr, ' is ', $DatacenterName, '. Is this correct?')
  'Color' = (White,Yellow,White,Yellow,White)
}
Write-Color -Text $Text -Color $Color

ラッパー関数を考えてみましょう:

Function Ask-ColoredQuestion ($Text, $Color) {
   Write-Color -Text $Text -Color $Color
   $host.ui.PromptForChoice($title, $message, $options, 0)
}

$splat = @{
  'Text' = ('The name of Datacenter ', $Curr, ' is ', $DatacenterName, '. Is this correct?')
  'Color' = (White,Yellow,White,Yellow,White)
}

$Result = Ask-ColoredQuestion @splat

さらに良いことに、テキストの色は、文字列の一部となるエスケープコードによって制御できます。これにより、組み込み-PromptパラメータのRead-Hostまたは$messageを使用できるようになります。PromptForChoice()

$esc = "$([char]27)"
$Red = "$esc[31m"
$Green = "$esc[32m"
$message = '{0}{1} {2}{3}' -f $Red, 'Hello', $Green, 'World'
$message

ここに画像の説明を入力してください

Write-Colorしたがって、カラー エスケープ コードを使用して文字列を作成し、その文字列を組み込みプロンプトに渡すようにツールを再設定する必要がある場合があります。

始めるにはこれで十分だと思います! :D

答え2

はい/いいえの回答を求めるプロンプトを多く実行していることに気づいたので、それを簡単にする関数を作成しました。これはいくつかのヒントを提供するかもしれませんが、私の努力をさらに改善したいと思われるかもしれません。

<#
.SYNOPSIS
    Prompts user for answer to a yes no prompt.
.DESCRIPTION
    The user is prompted with the argument, and asked for a reply.
    If the reply matches YES or NO (case insensitive) the value is true
    or false.  Otherwise, the user is prompted again.
#>
function ask-user {
    [CmdletBinding()]
    Param (
       [Parameter(Mandatory=$true)]
       [string] $question
    )
    Process {
       $answer = read-Host $question
       if ("YES","YE","Y" -contains $answer) {$true}
       elseif ("NO", "N" -contains $answer) {$false}
       else {ask-user $question}
    }
} # End function ask-user

関連情報