Return 声明无效

Return Statement not Working

更新

我可以通过将 Rename-Item 更改为 Move-Item 并在此过程中更改名称来解决此问题(这是一种让事情真正起作用的愚蠢方法)。然而,这并没有解开为什么 return 语句没有被执行的谜团,或者至少如果它被执行了,为什么函数继续调用 New-Item.


我想在登录时重命名一个项目,但如果该项目不存在,我想创建它。这是执行此操作的函数:

function SelfHelpAppData {
    $ErrorActionPreference = "Stop"
    trap {Log-Error $_ $MyInvocation.MyCommand; Continue}

    $files = Get-ChildItem $AppData

    ForEach ($file in $files) {
        If ($file.Name -match 'qxjz') {

            Rename-Item $file.PSPath "qxjz$env:COMPUTERNAME.txt" -Force
            WriteLogonEntryData
            return
        }
    }

    New-Item "$AppData\qxjz$env:COMPUTERNAME.txt"
    WriteLogonEntryData
}

然而,当这个 运行 时,我在我的日志中收到这些错误:

Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.

At \DC1\NETLOGON\PSSubs\mainlogon.ps1:841 char:5 + New-Item "$AppData\qxjz$env:COMPUTERNAME.txt" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

然后:

Cannot create a file when that file already exists.

At \DC1\NETLOGON\PSSubs\mainlogon.ps1:835 char:13 + Rename-Item $file.PSPath "qxjz$env:COMPUTERNAME.txt" -Force + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

但这是不可能的,因为如果第一行 (rename-item) 试图 运行,那么函数应该在另一行有机会之前 returned。我尝试将 return 语句更改为 return $null 但没有效果。有人知道这里发生了什么吗?

谢谢


这是日志错误代码:

function Log-Error {
    param (
        $error,
        [string]$sub
    )
    $ErrorActionPreference = "Stop"
    trap {Log-Error $_ $MyInvocation.MyCommand; Continue}

    $filename = "\file\administration\Unused\LogonScriptErrors$env:USERNAME - $env:COMPUTERNAME - $(Get-Date -Format ddMMyyyy-HHmmss) - $($error.InvocationInfo.ScriptLineNumber).log"

    New-Item $filename -ItemType File -Value "$($error.Exception.Message) `r`n `r`n $($error.InvocationInfo.PositionMessage) `r`n `r`n $sub"
}

您观察到的行为的原因是 trap 语句列表中的 continue。它会导致脚本在发生错误的循环之后继续执行下一条指令。这是 documented 行为。

如果您希望脚本在出现错误时终止操作,请删除 continue。如果你想要它只是退出功能更改 continuereturn.

话虽如此,我建议远离 trap 并改用 try/catch,这样可以提供更好的控制,甚至在视觉上也是如此。

顺便说一句,出现New-Item错误,因为你省略了强制参数-Type。如果没有该参数,cmdlet 会尝试提示您输入所需的信息,但不能,因为该脚本是 运行 非交互式的。要消除错误,请将 -Type File 添加到语句中。

每次都会抛出 PS 错误陷阱,因为 powershell 中的错误操作处理 "loose" 比传统的异常处理要多得多。我做了一些修改:

  • 使用 try/catch.
  • 而不是全局陷​​阱
  • 在您的新项目和重命名项目声明中使用 -Force
  • 您在 $env:AppData
  • 中忘记了 $env:
  • 您可以使用 | Out-Null
  • 来绕过控制台语句

在大多数情况下,单独进行 try/catch 错误处理既乏味又丑陋,这可能就是您选择 trap{} 的原因。如果您 真的 需要通过简单的 rename/create 文件操作进行错误处理,您可以只使用匹配案例进行一般异常处理。

function Do-Stuff {

    $EAPREF = 'Stop'
    $FILES = gci $env:APPDATA

    try {
        ForEach ($file in $FILES) {
            If ($file.Name -match 'qxjz') {
            Rename-Item $file.PSPath "qxjz$env:COMPUTERNAME.txt" -Force -ErrorAction $EAPREF | Out-Null
            return
            }
        }
        New-Item "$env:AppData\qxjz$env:COMPUTERNAME.txt" -ItemType 'File'  -Force -ErrorAction $EAPREF | Out-Null
    } 
    catch [System.Exception]{
        #Error handling here using type/parameter qualifier cases.

        if ($_.FullName -eq 'So and So'){
            # Handle the error a certain way for so-and-so
        }

        if ($_.FullName -eq 'Other exception type you expect'){
            # Handle another type of error separately
        }
    }
}