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
。如果你想要它只是退出功能更改 continue
到 return
.
话虽如此,我建议远离 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
}
}
}
更新
我可以通过将 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
。如果你想要它只是退出功能更改 continue
到 return
.
话虽如此,我建议远离 trap
并改用 try
/catch
,这样可以提供更好的控制,甚至在视觉上也是如此。
顺便说一句,出现New-Item
错误,因为你省略了强制参数-Type
。如果没有该参数,cmdlet 会尝试提示您输入所需的信息,但不能,因为该脚本是 运行 非交互式的。要消除错误,请将 -Type File
添加到语句中。
每次都会抛出 PS 错误陷阱,因为 powershell 中的错误操作处理 "loose" 比传统的异常处理要多得多。我做了一些修改:
- 使用 try/catch. 而不是全局陷阱
- 在您的新项目和重命名项目声明中使用
-Force
。 - 您在
$env:AppData
中忘记了 - 您可以使用
| Out-Null
来绕过控制台语句
$env:
在大多数情况下,单独进行 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
}
}
}