【发布时间】:2014-09-10 22:52:55
【问题描述】:
我写了一个函数来检查主机是在线还是离线并返回$true或$false。此功能完美运行,我想通过查看来改进它
是否可以删除脚本范围的变量,例如 $Script:arrayCanPingResult 和 $script:tmpPingCheckServers。
我为什么要这个?
当我在foreach 循环中调用该函数时,我通常使用开关-Remember,因此它不会检查同一主机两次。为了能够正确使用它,我必须通过将两个变量都声明为空($Script:arrayCanPingResult=$script:tmpPingCheckServers=@{})来开始我使用此函数的所有脚本。而且我可以想象人们忘记将第一行放在他们的脚本中,并且在 PowerShell ISE 编辑器中进行多次测试时,当主机已经在 ISE 中检查过一次(F5)时,它不会在第二次运行时再次进行测试.
在这种情况下,有没有办法避免使用脚本范围的变量?所以我们不需要在新脚本的开头声明它们为空?如果这是可能的,那就太好了,因为我们可以在自定义模块中包含这个函数。
一如既往,感谢您的建议或帮助。在你们这里我真的学到了很多东西。
# Function to check if $Server is online
Function Can-Ping ($Server,[switch]$Remember) {
$PingResult = {
# Return $true or $false based on the result from script block $PingCheck
foreach ($_ in $Script:arrayCanPingResult) {
# Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: $_ " -ForegroundColor Green
if ($Server -eq $($_.Split(",")[0])) {
#Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: We will return $($_.Split(",")[1])" -ForegroundColor Green
return $($_.Split(",")[1])
}
}
}
$PingCheck = {
$Error.Clear()
if (Test-Connection -ComputerName $Server -BufferSize 16 -Count 1 -ErrorAction 0 -quiet) { # ErrorAction 0 doesn't display error information when a ping is unsuccessful
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Ping test ok" -ForegroundColor Gray; $Script:arrayCanPingResult+=@("$Server,$true"); return
}
else {
$Error.Clear()
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Ping test FAILED" -ForegroundColor Gray
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Flushing DNS" -ForegroundColor Gray
ipconfig /flushdns | Out-Null
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Registering DNS" -ForegroundColor Gray
ipconfig /registerdns | Out-Null
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: NSLookup" -ForegroundColor Gray
nslookup $Server | Out-Null # Suppressing error here is not possible unless using '2> $null', but if we do this, we don't get $true or $false for the function so '| Out-Null' is an obligation
if (!$?) {
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: NSlookup can't find the host '$Server', DNS issues or hostname incorrect?" -ForegroundColor Yellow
# Write-Host $Error -ForegroundColor Red
if ($SendMail) {
Send-Mail $MailTo "FAILED Ping test" "$(Get-TimeStamp) NSlookup can't find the host '$Server', hostname incorrect or DNS issues?" "<font color=`"red`">$error</font>"
}
$script:arrayCanPingError += "ERROR | $(Get-TimeStamp) Ping test failed: NSlookup can't find the host '$Server', hostname incorrect or DNS issues?$error"
$script:HTMLarrayCanPingError += "ERROR | $(Get-TimeStamp) Ping test failed:<br>NSlookup can't find the host '$Server', hostname incorrect or DNS issues?<br><font color=`"red`">$error</font>"
$Script:arrayCanPingResult+=@("$Server,$false")
return
}
else {
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Re-pinging '$Server'" -ForegroundColor Gray
if (Test-Connection -ComputerName $Server -BufferSize 16 -Count 1 -ErrorAction 0 -Quiet) {
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Ping test ok, problem resolved" -ForegroundColor Gray
$Script:arrayCanPingResult+=@("$Server,$true")
return
}
else {
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: DNS Resolving is ok but can't connect, server offline?" -ForegroundColor Yellow
if ($SendMail) {
Send-Mail $MailTo "FAILED Ping test" "$error" "DNS Resolving is ok but can't connect to $Server, server offline?"
}
$script:arrayCanPingError += "ERROR Ping test failed: DNS Resolving is ok but can't connect to $Server, server offline?$error"
$script:HTMLarrayCanPingError += "ERROR Ping test failed: DNS Resolving is ok but can't connect to $Server, server offline?<br><font color=`"red`">$error</font>"
$Script:arrayCanPingResult+=@("$Server,$false")
return
}
}
}
}
# Call the script block $PingAction every time, unless the switch $Remember is provided, than we only check each server once
if ($Remember) {
Write-Host "$(Get-TimeStamp) $Server > Function Can-Ping: Switch '-Remember' detected" -ForegroundColor Gray
While ($tmpPingCheckServers -notcontains $Server) {
&$PingCheck
$script:tmpPingCheckServers = @($tmpPingCheckServers+$Server) #Script wide variable, otherwise it stays empty when we leave the function / @ is used to store it as an Array (table) instead of a string
}
&$PingResult
}
else {
&$PingCheck
&$PingResult
}
}
【问题讨论】:
-
简答:PSCustomObject。 IE。您想使用 object 作为参数,然后返回具有修改属性的相同对象。长答案取决于您的功能实际上应该做什么。你调用
Test-Connection一次,剩下的就是逻辑(这太复杂以至于无法阅读)和Write-Host调用(Write-Host 是邪恶的,在生产代码中避免它)。您能否提供输入和预期输出的示例? -
感谢您的回复。该函数像这样使用
Can-Ping -Remember SERVER1,如果SERVER1 在线,则返回$true,如果不在线,则返回$false。我第二次运行Can-Ping -Remember SERVER1它根本不会做任何测试并返回该服务器的最后一个已知结果。在我的脚本中,我每次在foreach循环中使用新的$Server名称调用此函数。然后根据结果检查PSRemoting功能和其他内容。
标签: variables powershell scope