当涉及函数返回值时,我们遇到了一些奇怪的PowerShell行为。
某些背景信息:
在我们的脚本和模块中,我们总是希望将$ErrorActionPreference
和$DebugPreference
设置为可通过函数检索的全局默认值。我们假设我们要将$DebugPreference
设置为"Continue"
以在我们的日志中包含其他消息。
所以,我们正在做这样的事情:
$DebugPreference = Get-GlobalDebugPreference
这是否是一个好方法不是这个问题的一部分。
问题:
在某些具有不同版本PowerShell的计算机上,这并没有按预期工作。当我们调用返回"Continue
"的函数时,$DebugPreference
确实存储了正确的值,但我们的日志文件中没有任何其他日志消息。
我们发现了什么:
Write-Debug
是否有效以某种方式与您返回值的方式相关联
"Continue
"来自管理全局默认值的函数。
E.g。当函数类似于以下示例时,Write-Debug按预期运行并在PowerShell 3中打印调试消息。但是,在PowerShell 2中,该值设置为"Continue
",但Write-Debug不会打印任何其他消息。
function Get-GlobalDebugPreference
{
return "Continue"
}
$DebugPreference = Get-GlobalDebugPreference
但是,如果我们只是将值放到shell上并省略return
语句,那么它适用于所有版本的PowerShell v2 +。
function Get-GlobalDebugPreference
{
"Continue"
}
$DebugPreference = Get-GlobalDebugPreference
有多种方法可以从PowerShell中的函数返回值。
对于某些方式,它适用于PS版本2,有些适用于v3。但是,使用Write-Output返回值"Continue
"不能达到v5。
在我看来,所有不同的方法应该可以正常工作,并且应该是可以互换的。对于这些基本的事情行为不同是令人担忧的,并使PowerShell有些不可预测。
我编写了一个小脚本,用$DebugPreference
设置不同的函数返回方法,这些方法应该都行为相同。如果使用不同版本的PowerShell运行它,则会获得不同数量的Debug输出。请注意,变量$DebugPreference
在每个步骤后都具有正确的值和正确的类型,但Write-Debug仅在其中一些步骤之后才起作用。
有人能解释一下这里发生了什么吗?
使用"powershell.exe -version 2 ...
"运行它给我这个输出:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
使用"powershell.exe -version 5 ...
"运行它给我这个输出:
Starting to test return values. Current DebugPreference: SilentlyContinue
1 Obtained the value with return: Continue with Type string
DEBUG: 1 After Get-GlobalDefaultWithReturn
2 Obtained the value from shell with return after: Continue with Type string
DEBUG: 2 After Get-GlobalDefaultWithReturnAfterwards
3 Obtained the value from shell with return after: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference
4 Obtained the value without return: Continue with Type string
DEBUG: 4 After Get-GlobalDefaultWithOutReturn
5 Obtained the value with Write-Output: Continue with Type string
6 Obtained the value with Write-Output: Continue with Type System.Management.Automation.ActionPreference
DEBUG: 6 After Get-GlobalDefaultWriteOutputActionPreference
7 Obtained piped value with Write-Output : Continue with Type string
8 Set the value directly: Continue with Type string
DEBUG: 8 After setting the value directly
剧本:
function Get-GlobalDefaultWithReturn
{
return "Continue"
}
function Get-GlobalDefaultWithReturnAfterwards
{
"Continue"
return
}
function Get-GlobalDefaultWithReturnAfterwardsActionPreference
{
([System.Management.Automation.ActionPreference]::Continue)
return
}
function Get-GlobalDefaultWithOutReturn
{
"Continue"
}
function Get-GlobalDefaultWriteOutput
{
Write-Output "Continue"
}
function Get-GlobalDefaultWriteOutputActionPreference
{
Write-Output ([System.Management.Automation.ActionPreference]::Continue)
}
$DebugPreference = "SilentlyContinue"
Write-Host "Starting to test return values. Current DebugPreference: $DebugPreference"
$DebugPreference = Get-GlobalDefaultWithReturn
Write-Host "1 Obtained the value with return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "1 After Get-GlobalDefaultWithReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwards
Write-Host "2 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "2 After Get-GlobalDefaultWithReturnAfterwards"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithReturnAfterwardsActionPreference
Write-Host "3 Obtained the value from shell with return after: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "3 After Get-GlobalDefaultWithReturnAfterwardsActionPreference"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWithOutReturn
Write-Host "4 Obtained the value without return: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "4 After Get-GlobalDefaultWithOutReturn"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutput
Write-Host "5 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "5 After Get-GlobalDefaultWriteOutput"
$DebugPreference = "SilentlyContinue"
$DebugPreference = Get-GlobalDefaultWriteOutputActionPreference
Write-Host "6 Obtained the value with Write-Output: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "6 After Get-GlobalDefaultWriteOutputActionPreference"
$DebugPreference = "SilentlyContinue"
Get-GlobalDefaultWriteOutput | % { $DebugPreference = $_ }
Write-Host "7 Obtained piped value with Write-Output : $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "7 After Get-GlobalDefaultWriteOutput with pipe"
$DebugPreference = "SilentlyContinue"
$DebugPreference = "Continue"
Write-Host "8 Set the value directly: $DebugPreference with Type $($DebugPreference.GetType())"
Write-Debug "8 After setting the value directly"
答案 0 :(得分:1)
之前我曾说过我没有这个问题,但似乎你运行代码的方式很重要,不包括运行为v2的ISE,Console和Higher Powershell版本,这就是我发现的:
没有问题:
有问题:
我建议的解决方法在这种情况下有效:
你可能想尝试(Get-GlobalDefaultWithReturn).tostring()来强制 如果那是问题就把它变成一个字符串。
Powershell版本:
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
它看起来像一个bug,但我还不知道更多关于它的信息。 确实有点不可预测,但您可能想要考虑运行代码的方式,例如:如果它是文件,请使用FILE。