我需要一些關于異步 Powershell 呼叫的幫助,該呼叫因 (1) 超出最大遞回深度或 (2) 輸入引數無效而失敗。
基本設定如下...
- 在 VSCode 中完成編碼和除錯
- Powershell 版本是 5.1.19041 - 桌面版
- 連接 SSAS 服務器的函式
- 第一個函式呼叫的遞回函式將物件轉換為 XML
- 創建一個 Powershell 會話以執行帶引數的函式
- BeginInvoke(),等待完成,處理結果
異步呼叫是否有什么東西弄亂了我的代碼,使得 $ NestLevel和 $MaxDepth 之間的比較無效或 $MaxDepth 設定為 0?
我已經檢查了一百次,我沒有看到任何地方 $MaxDepth 被設定為低于 1 的任何值。“if ($ NestLevel -gt $MaxDepth) { return }”應該終止遞回,但看起來不像這是。
我錯過了什么嗎?
代碼示例...
function Test-Recursion {
Param (
[Parameter(Mandatory=$false)]
$InputObject,
[Parameter(Mandatory=$false)]
[ValidateRange(1,100)]
[Int16] $MaxDepth = 2
)
[Int16] $_NestLevel_ = 1
if ( $_NestLevel_ -gt $MaxDepth ) { return }
"<item><nest_level>$($_NestLevel_)</nest_level><max_depth>$($MaxDepth)</max_depth></item>"
& $MyInvocation.MyCommand.ScriptBlock -InputObject $InputObject -MaxDepth $MaxDepth
}
function Get-Info {
Param (
[Parameter(Mandatory=$true)]
[String] $HostName,
[Parameter(Mandatory=$true)]
[ScriptBlock] $ConvertTo
)
$some_collection | `
ForEach-Object {
@(
$_as | ForEach-Object {
& $ConvertTo -InputObject $_ -MaxDepth 3
}
) | Sort-Object
}
}
# this code fails with either...
# - excessive recursion depth
# - invalid $MaxDepth value of 0
try {
$_ps = [powershell]::Create()
$null = $_ps.AddScript(${function:Get-Info})
$null = $_ps.AddParameter('HostName', 'some_server_name')
$null = $_ps.AddParameter('ConvertTo', ${function:Test-Recursion})
$_handle = $_ps.BeginInvoke()
while ( -Not $_handle.IsCompleted ) {
Start-Sleep -Seconds 5
}
$_result = $_ps.EndInvoke($_handle)
$_result
} catch {
$_
} finally {
$_ps.Dispose()
}
# this code works as expected
$items = Get-Info -HostName 'some_server_name' -ConvertTo ${function:Test-Recursion}
$items.table_data
uj5u.com熱心網友回復:
我不會詳細說明您希望使用這些函式完成什么,只是指出問題所在,由于您的函式不知道導致的無限回圈,您的powershell實體正在耗盡堆疊記憶體何時停止,因此添加了一個新引數( ),該引數將作為每個遞回呼叫的引數傳遞:Test-Recursion[Int16] $NestingLevel
function Test-Recursion {
Param (
[Parameter(Mandatory = $false)]
$InputObject,
[Parameter(Mandatory = $false)]
[ValidateRange(1,100)]
[Int16] $MaxDepth = 2,
[Parameter(DontShow)]
[Int16] $NestingLevel
)
[Int16] $NestingLevel = 1
if ( $NestingLevel -gt $MaxDepth ) {
return
}
"<item><nest_level>$NestingLevel</nest_level><max_depth>$MaxDepth</max_depth></item>"
Test-Recursion -InputObject $InputObject -MaxDepth $MaxDepth -NestingLevel $NestingLevel
}
Test-Recursion -InputObject hello -MaxDepth 3
還值得注意的是,您的遞回函式可以通過while回圈來簡化:
function Test-Recursion {
Param (
[Parameter(Mandatory = $false)]
$InputObject,
[Parameter(Mandatory = $false)]
[ValidateRange(1,100)]
[Int16] $MaxDepth = 2,
[Parameter(DontShow)]
[Int16] $NestingLevel
)
while($NestingLevel -lt $MaxDepth) {
"<item><nest_level>$NestingLevel</nest_level><max_depth>$MaxDepth</max_depth></item>"
}
}
關于您的最新評論:
根呼叫將變數初始化為 1。遞回呼叫將增加變數并有效地提供一種檢查當前嵌套級別的方法。
不,該變數存在于函式的每次呼叫中,然后在遞回呼叫后遞增的值丟失。$script:但是,您可以在范圍內初始化變數,然后它將起作用:
[Int16] $script:_NestLevel_ = 1
就個人而言,我不喜歡$script:在我的函式中使用作用域變數,我認為有更好的方法來做到這一點。
演示這一點的一種簡單方法是修改函式以$_NestLevel_在每次呼叫時輸出,原樣,您會看到無限量的內容1顯示在控制臺上。
function Test-Recursion {
Param (
[Parameter(Mandatory = $false)]
$InputObject,
[Parameter(Mandatory = $false)]
[ValidateRange(1,100)]
[Int16] $MaxDepth = 2
)
[Int16] $_NestLevel_ = 1
if ( $_NestLevel_ -gt $MaxDepth ) { return }
$_NestLevel_
& $MyInvocation.MyCommand.ScriptBlock -InputObject $InputObject -MaxDepth $MaxDepth
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/487132.html
