提问人:Alyxander VanHelsing 提问时间:5/16/2023 最后编辑:mklement0Alyxander VanHelsing 更新时间:5/16/2023 访问量:63
我知道您可以在 ForEach 循环中嵌套 IfElse 语句,但反之亦然吗?
I know you can nest an IfElse statement in a ForEach loop, but is the opposite also possible?
问:
多年来一直断断续续地使用 Powershell,但直到现在还没有真正进入那么多的自动化领域。我试图完成的是运行一个基于变量输入的语句。每个语句都会自行运行良好。测试的 ELSE 部分将在变量的输入下正常运行。然而。。。问题出在尝试基于变量的默认输入运行第一条语句时。这用于根据计算机名称验证用户的代理设置。我想使用相同的脚本来搜索/输出单台机器或从列表中搜索/输出,具体取决于收到的输入。
我已经尝试了我能想到的一切,以及我在互联网上能找到的一切。我怀疑我错过了一些简单的东西。当我在没有 ErrorAction 的情况下运行整个过程时,如果我在提示符中输入一个值,它将毫无问题地运行 ELSE 语句。然而。。。如果我接受默认值(我在那里放了什么并不重要,并且尝试了值的多次迭代),它只是直接跳到 ELSE 语句并出错,因为没有输入(没有要搜索的计算机名称)。
以下是编写的代码:
$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
}
}
任何帮助将不胜感激。谢谢。
答:
给定包含 Read-Host
调用的输出:$promptOutput
if ($null -eq $promptOutput) { ... }
是 never ,因为当用户只需按 Enter 键时,Read-Host
将返回空字符串,而不是 $null
。$true
因此,请使用:
if ('' -eq $promptOutput) { ... }
或者,假设空字符串隐式位于布尔上下文(如条件)中,则可以使用:$false
if
if (-not $promptOutput) { ... }
如果您还想将空白(全空格)输出视为与空输入相同的内容:if (-not $promptOutput.Trim()) { ... }
如果值的类型事先不知道,实际上可能是或不同的类型,只需将值括起来,首先将其强制转换为字符串:$null
"..."
if (-not "$unknownValue") { ... }
匹配或空字符串(相当于$null
[string]::IsNullOrEmpty()
)if (-not "$unknownValue".Trim()) { ... }
匹配 ,空字符串或空白(全空格)字符串(相当于 )。$null
[string]::IsNullOrWhiteSpace()
请注意,PowerShell 的设计通常不会将$null
存储在 [string]
类型的变量中:即使显式分配它也会存储(空字符串):$null
''
# Despite assigning $null, it is '' (empty string) that is stored.
[string] $str = $null; $null -eq $str # !! $false
虽然有一种使用单例存储实际 的变通方法,但最好避免使用它,但除了它的设计目的:将 true 传递给类型化的 .NET 方法参数。$null
[NullString]::Value
$null
[string]
评论
Read-Host
$null -eq $promptOutput
$null
if([string]::IsNullOrEmpty($promptOutput)) { ... }