【问题标题】:powershell if-else does not follow either branchpowershell if-else 不遵循任何一个分支
【发布时间】:2014-09-11 15:33:53
【问题描述】:

我有 powershell 代码

$target_dir = "\\server\share\"
$DelTmpStatus = "init value"
if ( Test-Path ( $target_dir + "receivals.tmp") )
{
    del ( $target_dir + "receivals.tmp")
    $DelTmpStatus = "Present and delete status $?"
} else {
    $DelTmpStatus = "NA"
}

有时它会在 $DelTmpStatus 仍设置为“初始值”的情况下通过此部分。

if-else 结构如何不遵循任何一条路径?当if函数给出错误而不是true或false时,powershell中的if-else结构是否不做任何事情?

$PSVersionTable.psversion 是 3.0

编辑:当我自己运行它时,我从来没有任何错误或这个问题,无论是完全还是逐步。但有时计划的作业会运行并且 $DelTmpStatus 仍将是“初始化值”我想它会发生在 \\server\share\ 路径不可用时,因为服务器在一夜之间处于低功耗模式,响应时间过长并且测试路径功能超时.虽然我不能确定这是否是原因。

编辑:测试结果

  • $target_dir 使用不存在的服务器使其遵循else 路径并将$DelTmpStatus 设置为“NA”
  • 使用像 $target_dir = "C:\..\..\invalid\" 这样的无效路径会导致 test-path 将错误写入 stderr 并返回 true(不理想,但无论如何),使程序继续尝试删除文件(再次出现错误)然后它将 $DelTmpStatus 设置为“呈现并删除状态 False”。这不是一件特别有用的事情,但至少执行了 if-else 语句中的代码。

【问题讨论】:

  • 您是否遇到任何错误?尝试设置断点,继续执行,看看会发生什么。
  • 我能想到的唯一情况是你有$ErrorActionPreference = 'Stop',而del 抛出异常,所以$DelTmpStatus 的设置被跳过。你在记录你的异常吗?
  • 虽然我没有设置$ErrorActionPreference,但它被设置为默认的继续。如果它被设置为停止,那不会停止整个脚本吗?如果您没有猜到,显示的代码只是完整脚本的摘录,该脚本继续运行并生成一个新的receivals.tmp 文件。我目前没有记录异常。
  • @BeowulfNode42,是的,如果它设置为“停止”,那么如果没有catch,脚本将停止。我没有解释。您可以使用一些不存在的服务器 ($target_dir = "\\blah\share\") 测试您的脚本,看看会发生什么。

标签: powershell if-statement boolean-logic


【解决方案1】:

似乎如果条件区域内的命令执行失败并且没有返回值,则整个if-else块都没有执行,并且continue on error选择在if-else块下面继续。

如何模拟问题

虽然这与我的实际代码中发生的情况不完全一样,但它确实会产生相同的问题,即 if-else 块没有被执行。它甚至每次都这样做。

if ( Test-Path -invalid-switch )
{
    write-output "true path of if statement"
} else {
    write-output "false path of if statement"
}
write-output "finished if statement"

有输出

Test-Path : A parameter cannot be found that matches parameter name 'invalid-switch'.
At C:\scripts\test.ps1:1 char:16
+ if ( Test-Path -invalid-switch )
+                ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Test-Path], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.TestPathCommand

finished if statement

修复

要解决此问题,需要将可能有错误的代码从预先测试的 if() 条件中取出,并将逻辑添加到 if 语句中以处理潜在的故障。为了修复实际代码以免遇到此问题,我现在将代码更改为

$err = $false
try { $tmpStatus = Test-Path ( $target_dir + "receivals.tmp") }
catch
{
    $tmpStatus = $error | foreach { $_.Exception }
    $err = $true
}
if ( $err -or $tmpStatus ) 
{
    del ( $target_dir + "receivals.tmp")
    $DelTmpStatus = $?
} else {
    $DelTmpStatus = "NA"
}

精明的人会意识到我可以只用线条替换所有这些

$tmpStatus = test-path ( $target_dir + "receivals.tmp")
del ( $target_dir + "receivals.tmp")
$DelTmpStatus = $?

因为我尝试删除该文件,即使它在查找文件时出错。唯一的区别是较短的代码会更频繁地出错,但仍然执行相同的功能。

但是,具有更多错误检查的更长代码可以更清楚地说明这种情况,因为 $tmpStatus 已经通过了值

System.Management.Automation.CommandNotFoundException: The term 'Test-Path' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

不幸的是,这仍然让我想知道发生了什么......? 'Test-Path' 如何在某些日子成为有效的 cmdlet,但在其他日子却不是,在同一台计算机上从同一个计划作业运行完全相同的脚本。作为额外的奖励,在 'Test-Path' is not a valid cmdlet 的日子里,当我稍后在同一个脚本中再次使用它时,它每次都能正常工作。

【讨论】:

    猜你喜欢
    • 2015-06-30
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-25
    相关资源
    最近更新 更多