Try / Catch或If / Else?

时间:2015-12-14 13:47:23

标签: powershell if-statement try-catch credentials

Hello Guys我在尝试弄清楚如何使这个脚本工作时遇到了麻烦,我在编写脚本方面非常新,但我确实理解了大部分内容但仍在弄清楚一些事情。

try {
    Test-Connection -Computername $_ -count 1 -ErrorAction Stop
} catch {
    $_.Exception.ErrorCode -eq 0x800706ba
} `
{
    $err = 'Unavailable (Host Offline or Firewall)'
}

try {
    Test-UserCredentials -Username testuser -Password (Read-Host -AsSecureString)
} catch {
    $_.CategoryInfo.Reason -eq 'UnauthorizedAccessException'
} `
{
    $err = 'Access denied (Check User Permissions)'
}

Write-Warning "$computer- $err" | Out-File -FilePath c:\temp\Folder\Errors.txt -Append

我正在寻找的是这个脚本来测试系统是否响应。如果为True则下一步将是测试凭据,最后一步是执行get-wmiobject查询。但是如果系统没有响应ping,那么我想捕获无法响应ping的主机名,捕获它并将其导出到txt并在凭证失败时执行相同的操作。

3 个答案:

答案 0 :(得分:7)

try..catch用于处理终止错误。不要滥用它进行状态检查,强制检查在不需要的时候努力。如果您只想使用参数Test-Connection作为-Quiet条件来测试系统运行if的可用性:

if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
  ...
}

如果您需要级联多个检查,您可以通过反转检查并使用适当的消息返回来以更易读的方式执行此操作:

function Test-Multiple {
  ...
  if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
    return "Host $_ unavailable."
  }

  $pw = Read-Host -AsSecureString
  if (-not (Test-UserCredentials -Username testuser -Password $pw)) {
    return 'Login failed for user testuser.'
  }
  ...
}

如果您想了解日志文件中有关ping或登录失败的信息,您可以将其附加到相应的文件中:

function Test-Multiple {
  ...
  if (-not (Test-Connection -ComputerName $_ -Count 1 -Quiet)) {
    $_ | Add-Content 'C:\path\to\unavailable.log'
    return
  }

  $pw = Read-Host -AsSecureString
  if (-not (Test-UserCredentials -Username testuser -Password $pw)) {
    $_ | Add-Content 'C:\path\to\login_failure.log'
    return
  }
  ...
}

答案 1 :(得分:2)

就个人而言,我无法忍受Test-Connection的行为。在没有成功ping的情况下抛出异常并不是我想要的行为。就像,永远。我明白为什么他们这样做,但不是我希望ping工作的方式。当路径无效时,Test-Path不会抛出异常。它只返回false。为什么Test-Connection如此不友好?

WMI允许您捕获实际状态代码,它还允许您轻松控制超时,以便它可以更快地运行。

我倾向于使用它:

$Ping = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000";
if ($Ping.StatusCode -eq 0) {
    # Success
}
else {
    # Failure
}

如果我真的想解码ping状态码:

$StatusCodes = @{
    [uint32]0     = 'Success';
    [uint32]11001 = 'Buffer Too Small';
    [uint32]11002 = 'Destination Net Unreachable';
    [uint32]11003 = 'Destination Host Unreachable';
    [uint32]11004 = 'Destination Protocol Unreachable';
    [uint32]11005 = 'Destination Port Unreachable';
    [uint32]11006 = 'No Resources';
    [uint32]11007 = 'Bad Option';
    [uint32]11008 = 'Hardware Error';
    [uint32]11009 = 'Packet Too Big';
    [uint32]11010 = 'Request Timed Out';
    [uint32]11011 = 'Bad Request';
    [uint32]11012 = 'Bad Route';
    [uint32]11013 = 'TimeToLive Expired Transit';
    [uint32]11014 = 'TimeToLive Expired Reassembly';
    [uint32]11015 = 'Parameter Problem';
    [uint32]11016 = 'Source Quench';
    [uint32]11017 = 'Option Too Big';
    [uint32]11018 = 'Bad Destination';
    [uint32]11032 = 'Negotiating IPSEC';
    [uint32]11050 = 'General Failure'
    };

$Ping = Get-WmiObject -Class Win32_PingStatus -Filter "Address='$ComputerName' AND Timeout=1000"

$StatusCodes[$Ping.StatusCode];

答案 2 :(得分:1)

你可以这样做:

if(Test-Connection -Computername $_ -Count 2 -ErrorAction 0 -Quiet) {
    if(-not (Test-UserCredentials -Username testuser -Password (Read-Host -AsSecureString))) {
        $err = "Access denied (Check User Permissions)"
    }
} else {
    $err = "Unavailable (Host Offline or Firewall)"
}

if($err) {
    Write-Warning "$computer - $err" | Out-File -FilePath c:\temp\Folder\Errors.txt -Append
}

我相信Test-ConnectionTest-Credentials意味着返回$ true或$ false而非异常(如果使用得当),所以你真的不需要try / catch在这里。