Been using Powershell on and off for years but haven't really gotten into that much automation until now. What I'm trying to accomplish is running a statement based on input for a variable. Each statement will run just fine by itself. The ELSE part of the test will run just fine with input from the variable. However...the issue comes in with trying to run the first statement based on the default input for the variable. This is for verifying proxy settings for users based on machine name. I would like to use the same script to search/output either a single machine or from a list, depending on the input received.
I've tried everything I can think of and everything I can find on the internet. I have a suspicion that I am missing something simple. When I run the whole thing without the ErrorAction, it will run the ELSE statement with no issues if I enter a value into the prompt. However...if I accept the default value (hasn't mattered what I put in there and have tried multiple iterations of values) it just skips directly to the ELSE statement and errors out since there isn't an input (no computer name to search on).
Here is the code as written:
$ErrorActionPreference = "SilentlyContinue"
$pathHKU = 'HKU:\.Default\Environment\'
$pathExists = Test-Path -Path $pathHKU
If(!($pathExists))
{
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_Users
}
$defaultValue = ""
$preSID = "Get-ItemPropertyValue 'registry::HKU\"
$postSID = "\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name ProxyServer"
$promptOutput = Read-Host "Press enter to search by list or type in the name of a single machine [$($defaultValue)]"
IF($null -eq $promptOutput) {
$sysName | Add-Content -Path ".\testlist.txt"
ForEach ($sys in $sysName)
{
$SID = Invoke-Command -ComputerName $sys -ScriptBlock {Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Username | ForEach-Object { ([System.Security.Principal.NTAccount]$_).Translate([System.Security.Principal.SecurityIdentifier]).Value}}
$searchProxy = $preSID+$SID+$postSID
$scriptBlock = [Scriptblock]::Create($searchProxy)
ForEach ($script in $scriptBlock) {
$userProxy = Invoke-Command -ComputerName $sys -ScriptBlock $scriptBlock
}
$sys+" - "+$userProxy | Out-File -Path ".\TestProxySettings.csv" -Append
}
}else{
$nameComp = $promptOutput
$SID = Invoke-Command -ComputerName $nameComp -ScriptBlock {Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Username | ForEach-Object { ([System.Security.Principal.NTAccount]$_).Translate([System.Security.Principal.SecurityIdentifier]).Value}}
$searchProxy = $preSID+$SID+$postSID
$scriptBlock = [Scriptblock]::Create($searchProxy)
ForEach ($script in $scriptBlock) {
$userProxy = Invoke-Command -ComputerName $nameComp -ScriptBlock $scriptBlock
$nameComp+" - "+$userProxy
}
}
Any help will be greatly appreciated. Thank you.
Given that $promptOutput
contains the output from a Read-Host
call:
if ($null -eq $promptOutput) { ... }
is never $true
, because Read-Host
returns the empty string, not $null
, when the user just presses Enter.
Therefore, use:
if ('' -eq $promptOutput) { ... }
Or, given that the empty string is implicitly $false
in a Boolean context such as an if
conditional, you can use:
if (-not $promptOutput) { ... }
if (-not $promptOutput.Trim()) { ... }
In cases where the value's type isn't known in advance and may actually be $null
or a different type, simply enclose the value in "..."
to coerce it to a string first:
if (-not "$unknownValue") { ... }
to match $null
or the empty string (equivalent of [string]::IsNullOrEmpty()
)if (-not "$unknownValue".Trim()) { ... }
to match $null
, the empty string, or blank (all-whitespace) strings (equivalent of [string]::IsNullOrWhiteSpace()
).Note that PowerShell by design in general doesn't store $null
in [string]
-typed variables: even when explicitly assigning $null
it stores ''
(the empty string) instead:
# Despite assigning $null, it is '' (empty string) that is stored.
[string] $str = $null; $null -eq $str # !! $false
While there is a workaround for storing actual $null
, using the [NullString]::Value
singleton, its use is best avoided, except for what it was designed for: passing a true $null
to [string]
-typed .NET method parameters.