Is there a way to get Read-Host to recognize PowerShell multipliers like KB, MB,GB,TB, and PB? The first example works just fine if I populate the $freespace variable by hand but does not work in the second example using Read-Host to populate the $freespace variable. The has to be a simple solution to get prompt for user input and have the value recognized as an integer rather than a string.
#this works just fine. The PowerShell multiplier GB is recognized if typed in.
$freespace = 6GB
If ($freeSpace -le 5GB) {
Write-Host “Free disk space is less than 5 GB”
} ElseIf ($freeSpace -le 10GB) {
Write-Host “Free disk space is less than 10 GB”
} ElseIf ($freeSpace -le 20GB) {
Write-Host “Free disk space is less than 20 GB”
} Else {
Write-Host “Free disk space is more than 20 GB”
}
#This does not work. The variable is populated by Read-Host as a [string]
$freespace = Read-Host -Prompt 'Please enter a value for Freespace'
If ($freeSpace -le 5GB) {
Write-Host “Free disk space is less than 5 GB”
} ElseIf ($freeSpace -le 10GB) {
Write-Host “Free disk space is less than 10 GB”
} ElseIf ($freeSpace -le 20GB) {
Write-Host “Free disk space is less than 20 GB”
} Else {
Write-Host “Free disk space is more than 20 GB”
}
CodePudding user response:
When you do this:
$freespace = Read-Host -Prompt 'Please enter a value for Freespace'
The value stored in the $freespace
variable will be of type [String]
, whereas you probably want [UInt64]
(positive integer). You can convert the [String]
type to the [UInt64]
type using code like the following:
do {
$entry = Read-Host "Please enter a value for freespace, in GB"
$freespace = $entry -as [UInt64]
$ok = ($null -ne $freespace) -and ($freespace -lt 1024)
if ( -not $ok ) {
Write-Host "Please enter a value in the range 0 to 1023"
}
until ( $ok )
$freespace *= 1GB
First, you prompt for a [String]
and store it in $entry
. Next, we cast the string value to an [Int]
value using the -as
operator. If the conversion fails, the $freespace
variable will contain $null
. The do
loop will repeat until a numeric value is entered.
With the above code in your script, $freespace
will be a numeric value after the do
loop completes. The final line converts it to GB.
CodePudding user response:
your read host is a string not an int try the below
[int]$freespace = Read-Host -Prompt 'Please enter a value for Freespace'
CodePudding user response:
Correction
$freeSpace = $null
do {
[int]$freeSpaceRaw = Read-Host -Prompt 'Please enter a value for Freespace in GB example 5 for 5GB '
try { $freeSpace = 0 $freeSpaceRaw } catch { Write-Warning 'Please enter a valid number.' }
} while ($null -eq $freeSpace)
If ($freeSpace -lt 5) {
"Free disk space is less than 5 GB"
} ElseIf ($freeSpace -lt 10) {
"Free disk space is less than 10 GB"
} ElseIf ($freeSpace -lt 20) {
"Free disk space is less than 20 GB"
} Else {
"Free disk space is more than 20 GB"
}
CodePudding user response:
Windows PowerShell only recognizes the binary multiplier suffixes - kb
, mb
, gb
, tb
, pb
- in number literals, and not when (implicitly) converting from a string, the latter being what the Read-Host
cmdlet invariably returns.
The only context where the string form is recognized is an operator-based expression in which a string operand is implicitly converted to a number, which enables a fairly simple and safe workaround.[1]
PS> 0 '1kb'
1024
This workaround also works in PowerShell (Core) 7 , but there you could simply use
[long] '1kb'
, because such strings are now consistently supported during implicit to-number conversion.
Applied to your code:
while ($true) {
try {
$freeSpace = 0 (Read-Host -Prompt 'Please enter a value for Freespace')
break # Valid input received; exit the loop.
} catch {
Write-Warning 'Please enter a valid number.' # Prompt again.
}
}
If ($freeSpace -lt 5GB) {
"Free disk space is less than 5 GB"
} ElseIf ($freeSpace -lt 10GB) {
"Free disk space is less than 10 GB"
} ElseIf ($freeSpace -lt 20GB) {
"Free disk space is less than 20 GB"
} Else {
"Free disk space is more than 20 GB"
}
[1] While using Invoke-Expression
(iex
) would technically work too, this cmdlet should generally be avoided and used only as a last resort, due to its inherent security risks. Superior alternatives are usually available. If there truly is no alternative, only ever use it on input you either provided yourself or fully trust - see this answer.