0

更新

我能够通过在过程中更改并仅更改名称来解决此问题Rename-ItemMove-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 处于非交互模式。阅读和提示功能不可用。

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

接着:

当该文件已存在时无法创建该文件。

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

但这是不可能的,好像第一行 (rename-item) 试图运行,那么函数应该在另一行有机会之前返回。我尝试将 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"
}
4

2 回答 2

2

您观察到的行为的原因是continue在您的trap声明列表中。它使脚本在发生错误的循环之后继续执行下一条指令。这是记录在案的行为。

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

话虽如此,我建议远离trap并使用try/catch代替,它可以提供更好的控制,甚至在视觉上。

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

于 2016-04-04T15:27:42.650 回答
1

每次都会抛出 PS 错误陷阱,因为 powershell 中的错误操作处理比传统的异常处理更“松散”。我做了一些修改:

  • 使用 try/catch,而不是做一个全局的毯子陷阱。
  • -Force在您的 new-item 和 rename-item 语句中使用。
  • 你忘记$env:$env:AppData
  • 你可以绕过控制台措辞| Out-Null

在大多数情况下,进行单独的 try/catch 错误处理既乏味又丑陋,这可能就是您选择trap{}. 如果您确实需要通过简单的重命名/创建文件操作进行该级别的错误处理,则可以使用匹配案例进行一般异常处理。

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
        }
    }
}
于 2016-04-04T15:50:13.043 回答