
close
close
Upcoming FREE Conference on Identity Management and Privileged Access Management
In a previous article I guided you through some variations on using Read-Host to prompt for user input. It’s not too surprising that I couldn’t leave the topic alone. I just had to keep working with it, and I came up with something else that I hope you’ll fine equally helpful. I wanted to take Read-Host to the next level and create a tool that will let you write better scripts.
Let’s say you are using Read-Host in a script or function to prompt for additional information. You might start with something like this:
$name = Read-Host "Enter a user name"
You most likely need to validate it, perhaps to make sure something was entered.
if ($name) { #code to continue #... } else { Write-Warning "You didn't enter a user name" }
Another option is to use one of the parameter validation checks. They are really variable validation tests, and you can use them anywhere.
[ValidatePattern("\w+")]$name = Read-Host "Enter a user name"
Using a validation test (Image Credit: Jeff Hicks)
Function Read-HostSpecial { [cmdletbinding(DefaultParameterSetName="_All")] Param( [Parameter(Position = 0,Mandatory,HelpMessage = "Enter prompt text.")] [Alias("message")] [ValidateNotNullorEmpty()] [string]$Prompt, [Alias("foregroundcolor","fg")] [consolecolor]$PromptColor, [string]$Title, [Parameter(ParameterSetName = "SecureString")] [switch]$AsSecureString, [Parameter(ParameterSetName = "NotNull")] [switch]$ValidateNotNull, [Parameter(ParameterSetName = "Range")] [ValidateNotNullorEmpty()] [int[]]$ValidateRange, [Parameter(ParameterSetName = "Pattern")] [ValidateNotNullorEmpty()] [regex]$ValidatePattern, [Parameter(ParameterSetName = "Set")] [ValidateNotNullorEmpty()] [string[]]$ValidateSet ) Write-Verbose "Starting: $($MyInvocation.Mycommand)" Write-Verbose "Parameter set = $($PSCmdlet.ParameterSetName)" Write-Verbose "Bound parameters $($PSBoundParameters | Out-String)" #combine the Title (if specified) and prompt $Text = @" $(if ($Title) { "$Title`n$("-" * $Title.Length)" }) $Prompt : "@ #create a hashtable of parameters to splat to Write-Host $paramHash = @{ NoNewLine = $True Object = $Text } if ($PromptColor) { $paramHash.Add("Foregroundcolor",$PromptColor) } #display the prompt Write-Host @paramhash #get the value if ($AsSecureString) { $r = $host.ui.ReadLineAsSecureString() } else { #read console input $r = $host.ui.ReadLine() } #assume the input is valid unless proved otherwise $Valid = $True #run validation if necessary if ($ValidateNotNull) { Write-Verbose "Validating for null or empty" if($r.length -eq 0 -OR $r -notmatch "\S" -OR $r -eq $Null) { $Valid = $False Write-Error "Validation test for not null or empty failed." } } elseif ($ValidatePattern) { Write-Verbose "Validating for pattern $($validatepattern.ToString())" If ($r -notmatch $ValidatePattern) { $Valid = $False Write-Error "Validation test for the specified pattern failed." } } elseif ($ValidateRange) { Write-Verbose "Validating for range $($ValidateRange[0])..$($ValidateRange[1]) " if ( -NOT ([int]$r -ge $ValidateRange[0] -AND [int]$r -le $ValidateRange[1])) { $Valid = $False Write-Error "Validation test for the specified range ($($ValidateRange[0])..$($ValidateRange[1])) failed." } else { #convert to an integer [int]$r = $r } } elseif ($ValidateSet) { Write-Verbose "Validating for set $($validateset -join ",")" if ($ValidateSet -notcontains $r) { $Valid = $False Write-Error "Validation test for set $($validateset -join ",") failed." } } If ($Valid) { Write-Verbose "Writing result to the pipeline" #any necessary validation passed $r } Write-Verbose "Ending: $($MyInvocation.Mycommand)" } #end function #define an alias Set-Alias -Name rhs -Value Read-HostSpecial
The function uses several parameter sets for the different validation tasks you might want. At a minimum, all you need to enter is a message prompt. Instead of using Read-Host, I use the Readline() method to get the input.
$r = $host.ui.ReadLine()
I do this because I’m using Write-Host to display the prompt text as well as an optional title.
$Text = @" $(if ($Title) { "$Title`n$("-" * $Title.Length)" }) $Prompt : "@
In the here string I have inserted some logic in the form of an If statement. If there is a title, then it is inserted along with a string of —- that match the length. By using Write-Host, I can take advantage of its ForegroundColor parameter.
$paramHash = @{ NoNewLine = $True Object = $Text } if ($PromptColor) { $paramHash.Add("Foregroundcolor",$PromptColor) } #display the prompt Write-Host @paramhash
Using Read-HostSpecial (Image Credit: Jeff Hicks)
Entering a secure string (Image Credit: Jeff Hicks)
Validating not null or empty (Image Credit: Jeff Hicks)
Validating on a pattern (Image Credit: Jeff Hicks)
Validating on a set (Image Credit: Jeff Hicks)
Validating a range (Image Credit: Jeff Hicks)
More in PowerShell
Most popular on petri