Common/Wrappers/Wrappers.psm1
function Read-RMUUID { param ( [string] $UserMessage, [string] $ParameterName, [bool] $IsRequired ) while ($true) { $ReadValue = Read-Host $UserMessage if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } } $Tokens = $ReadValue -split "," $InvalidUUIDs = @() $ResultIDs = @() foreach ($Token in $Tokens) { $Token = $Token.Trim() try { $ResultIDs += [System.Guid] $Token } catch { $InvalidUUIDs += $Token } } if ($InvalidUUIDs.Count -gt 0) { $InvalidUUIDsAsString = $InvalidUUIDs -join ", " Write-RMError -Message ("Invalid UUID {0}, please try again" -f $InvalidUUIDsAsString) continue } return $ResultIDs } } function Read-RMString { param ( [Parameter(Mandatory)] [string] $UserMessage, [string[]] $Options, [string] $DefaultValue, [Parameter(Mandatory)] [string] $ParameterName, [Parameter(Mandatory)] [bool] $IsRequired ) Confirm-RMInputParameter -InputParameter $PSBoundParameters $UserPrompt = $UserMessage if ($Options.Count -gt 0) { $UserPrompt += " (" + ($Options -join ",") + ")" } if (![string]::IsNullOrEmpty($DefaultValue)) { if ($Options.Count -eq 0) { $UserPrompt += " [" + $DefaultValue + "]" } else { $UserPrompt += "[" + $DefaultValue + "]" } } while ($true) { $ReadValue = Read-Host $UserPrompt if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } elseif("None" -ieq $DefaultValue) { return "" } else { return $DefaultValue } } if (0 -ne $Options.Count -and $Options -notcontains $ReadValue) { Write-RMError -Message ($ParameterName + " should be " + ($Options -join " or ") + ", please try again") continue } return $ReadValue } } function Read-RMBoolean { param( [string] $UserMessage, [Parameter(Mandatory)] [string] $DefaultValue ) $UserPrompt = $UserMessage if (![string]::IsNullOrEmpty($DefaultValue)) { $UserPrompt += " (true,false)" + "[" + $DefaultValue + "]" } while ($true) { $ReadValue = Read-Host $UserPrompt if ("" -eq $ReadValue) { return [System.Convert]::ToBoolean($DefaultValue) } try { return [System.Convert]::ToBoolean($ReadValue) } catch { Write-RMError -Message "Invalid boolean value '$ReadValue', please try again" continue } } } function Read-RMInt { param( [Parameter(Mandatory)] [string] $UserMessage, [int[]] $Options, [int[]] $OptionsRange, [string] $DefaultValue, [Parameter(Mandatory)] [string] $ParameterName, [Parameter(Mandatory)] [bool] $IsRequired ) Confirm-RMInputParameter -InputParameter $PSBoundParameters if ($OptionsRange.Count -gt 0 -and $OptionsRange.Count -ne 2) { throw "The parameter OptionsRange length should be exactly equal to 2, actual length is: " +$OptionsRange.Count } $UserPrompt = $UserMessage if ($Options.Count -eq 1 -and [string]::IsNullOrEmpty($DefaultValue)) { } if ($Options.Count -gt 0) { $UserPrompt += " (" + ($Options -join ",") + ")" } elseif ($OptionsRange.Count -gt 0) { $UserPrompt += " (" + ($OptionsRange -join "-") + ")" } if (![string]::IsNullOrEmpty($DefaultValue)) { if ($Options.Count -eq 0) { $UserPrompt += " [" + $DefaultValue + "]" } else { $UserPrompt += "[" + $DefaultValue + "]" } } while ($true) { $ReadValue = Read-Host $UserPrompt if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } elseif("None" -eq $DefaultValue) { return 0 } else { return [int] $DefaultValue } } if (-not($ReadValue -match "^[\d]+$")) { Write-RMError -Message "Please enter an integer value only" continue } if (0 -ne $Options.Count -and $Options -notcontains $ReadValue) { Write-RMError -Message ($ParameterName + " should be " + ($Options -join " or ") + ", please try again") continue } elseif ($OptionsRange.Count -gt 0) { $ReadValue = [int]$ReadValue if(-not($ReadValue -ge $OptionsRange[0] -and $ReadValue -le $OptionsRange[1])) { Write-RMError -Message ($ParameterName + " should be in range " + ($OptionsRange -join "-") + ", please try again") continue } } return $ReadValue } } function Read-RMIPAddress { param( [Parameter(Mandatory)] [string] $UserMessage, [string] $DefaultValue, [Parameter(Mandatory)] [string] $ParameterName, [Parameter(Mandatory)] [bool] $IsRequired ) Confirm-RMInputParameter -InputParameter $PSBoundParameters $UserPrompt = $UserMessage if (![string]::IsNullOrEmpty($DefaultValue)) { $UserPrompt += " [" + $DefaultValue + "]" } while ($true) { $ReadValue = Read-Host $UserPrompt if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } elseif("None" -ieq $DefaultValue) { return "" } else { return $DefaultValue } } $IPPattern = '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' if ($ReadValue -notmatch $IPPattern) { Write-RMError -Message ($ReadValue + " is not a valid IP address, please try again") continue } return $ReadValue } } function Read-RMDate { param( [Parameter(Mandatory)] [string] $UserMessage, [Parameter(Mandatory)] [string] $DateFormat, [string] $DefaultValue, [Parameter(Mandatory)] [string] $ParameterName, [bool] $IsRequired ) Confirm-RMInputParameter -InputParameter $PSBoundParameters $UserPrompt = $UserMessage if (![string]::IsNullOrEmpty($DefaultValue)) { $UserPrompt += "[" + $DefaultValue + "]" } while ($true) { $ReadValue = Read-Host $UserPrompt $ReadValue = $ReadValue.Trim() if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } elseif("None" -ieq $DefaultValue) { return "" } else { return $DefaultValue } } try { [datetime]::ParseExact($ReadValue, $DateFormat, $null) return $ReadValue } catch { Write-RMError -Message ("{0} format is incorrect, expected date format is {1}" -f $ParameterName, $DateFormat) continue } } } function Read-RMToken { param( [Parameter(Mandatory)] [string] $UserMessage, [Parameter(Mandatory)] [string] $Separator, [Parameter(Mandatory)] [string] $ParameterName, [string] $DefaultValue, [bool] $IsRequired ) Confirm-RMInputParameter -InputParameter $PSBoundParameters $UserPrompt = $UserMessage if (![string]::IsNullOrEmpty($DefaultValue)) { $UserPrompt += "[" + $DefaultValue + "]" } $Result = @() while ($true) { $ReadValue = Read-Host $UserPrompt $ReadValue = $ReadValue.Trim() if ("" -eq $ReadValue) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } elseif("None" -ieq $DefaultValue) { return "" } else { return $DefaultValue } } $Tokens = $ReadValue.Split($Separator) foreach ($Token in $Tokens) { $Result += $Token.Trim() } return $Result } } function Read-RMPair { param( [Parameter(Mandatory)] [string] $UserMessage, [string] $Separator, [string] $DefaultValue ) $UserPrompt = $UserMessage if (![string]::IsNullOrEmpty($DefaultValue)) { $UserPrompt += " [" + $DefaultValue + "]" } while ($true) { $ReadValue = Read-Host $UserPrompt $ReadValue = $ReadValue.Trim() if ("" -eq $ReadValue) { if ("none" -ieq $DefaultValue) { return "" } return $DefaultValue } if (-not(Confirm-RMPair -UserInput $ReadValue -Separator $Separator)) { continue } return $ReadValue } } function Read-RMMigrationSchedule { param () $Schedule = Read-RMString -UserMessage "Schedule for now or later" -Options "Now", "Later" ` -DefaultValue "Now" -ParameterName "Schedule" -IsRequired $false if ("Now" -eq $Schedule) { return "" } while ($true) { $ScheduleTime = Read-RMString -UserMessage "Enter the schedule in the format 'MM/dd/yyyy HH:mm'" -ParameterName "Schedule date time" -IsRequired $true $IsValidDateTime = Confirm-RMDateFormat -InputDate $ScheduleTime -DateFormat "MM/dd/yyyy HH:mm" if ($IsValidDateTime) { if (!(Confirm-RMAfterCurrentDateTime -InputDateTime $ScheduleTime)) { Write-RMError -Message "The entered schedule is not after the current time, please try again." continue } } else { Write-RMError -Message "The entered schedule is not in the format 'MM/dd/yyyy HH:mm', please try again." continue } return (Convert-RMDateTimeToUTC -InputDateTime $ScheduleTime) } } function Read-RMSecureString { param( [string] $UserMessage, [string] $ConfirmMessage, [string] $ParameterName, [string] $ConfirmParameterName, [bool] $IsRequired ) while ($true) { $ReadValue = Read-Host $UserMessage -AsSecureString $SecurePassword = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($ReadValue) $Password = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($SecurePassword) if ("" -eq $Password) { if ($IsRequired) { Write-RMError -Message ($ParameterName + " is required, please try again") continue } } if ([string]::IsNullOrEmpty($ConfirmMessage)) { # No need to confirm the password return $Password } $ReadValue = Read-Host $ConfirmMessage -AsSecureString $SecureConfirmPassword = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($ReadValue) $ConfirmPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($SecureConfirmPassword) if ($Password -ne $ConfirmPassword) { Write-RMError -Message ($ParameterName + " and " + $ConfirmParameterName + " do not match, please try again") continue } return $Password } } function Confirm-RMPair { param( [string] $UserInput, [string] $Separator ) $Tokens = $UserInput -split "," $IsValidInput = $true foreach ($Token in $Tokens) { $Token = $Token.Trim() if (!$Token.Contains($Separator)) { Write-RMError -Message "'$Token' does not contain '$Separator', please try again" $IsValidInput = $false continue } $Pair = $Token -split $Separator if ($Pair.Count -ne 2 -or [string]::IsNullOrEmpty($Pair[0]) -or [string]::IsNullOrEmpty($Pair[1])) { Write-RMError -Message ("$Token is not in the format key $Separator value, please try again") $IsValidInput = $false continue } } return $IsValidInput } function Confirm-RMInputParameter { param( [hashtable] $InputParameter ) if ($InputParameter.ContainsKey("DefaultValue") -and $InputParameter.ContainsKey("IsRequired")) { if (![string]::IsNullOrEmpty($InputParameter["DefaultValue"]) -and $InputParameter["IsRequired"] -eq $true) { throw "Incorrect usage of wrapper method, cannot invoke '{0}' with a default value and IsRequired as true" ` -f $MyInvocation.MyCommand } if ($InputParameter["IsRequired"] -eq $false -and [string]::IsNullOrEmpty($InputParameter["DefaultValue"])) { throw "Incorrect usage of wrapper method, cannot invoke '{0}' with no default value and IsRequired as false" ` -f $MyInvocation.MyCommand } } } function Confirm-RMDateFormat { param( [string] $InputDate, [string] $DateFormat ) if([string]::IsNullOrEmpty($InputDate)) { return $true } try { [datetime]::ParseExact($InputDate, $DateFormat, $null) |Out-Null } catch { return $false } return $true } function Confirm-RMAfterCurrentDateTime { param( [string] $InputDateTime ) $Date, $Time = Split-RMDateTime -InputDateTime $InputDateTime $DateTimeObjByInput = Get-Date -Month $Date[0] -Day $Date[1] -Year $Date[2] -Hour $Time[0] -Minute $Time[1] $CurrentDateTimeObj = Get-Date -Format "MM/dd/yyyy HH:mm" return ($DateTimeObjByInput -gt $CurrentDateTimeObj) } function Convert-RMDateTimeToUTC { param( [string] $InputDateTime ) <# We could have converted string to DateTime Object but the DateTime object will treat given date and time in the format that is standard for the given system locale. Hence, we are restricting the date time format to be "MM/dd/yyyy HH:mm" and explicitly parsing it here and getting the DateTime object from Get-Date by giving individual date and time parameters to it. It's the callers responsibility to validate the given date time by calling "Confirm-RMDateFormat" and then call this method. #> $Date, $Time = Split-RMDateTime -InputDateTime $InputDateTime return (Get-Date -Month $Date[0] -Day $Date[1] -Year $Date[2] -Hour $Time[0] -Minute $Time[1]).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:00.000K") } function Split-RMDateTime { param( [string] $InputDateTime ) $DateTime = $InputDateTime -split " " $Date = $DateTime[0] -split "/" $Time = $DateTime[1] -split ":" return $Date, $Time } function Write-RMError { param ( [string] $Message ) [Console]::ForegroundColor = 'red' [Console]::Error.WriteLine($message) [Console]::ResetColor() } |