【问题标题】:Powershell script works interactively, not within a scriptPowershell 脚本以交互方式工作,而不是在脚本内
【发布时间】:2013-08-09 18:13:19
【问题描述】:

代码以交互方式工作,而在 PS1 文件中则不然。要重现,打开 powershell,粘贴函数,然后运行 ​​get-job 以查看任务。类型得到工作 |完成后删除作业,然后将代码放入 PS1 文件中,它只运行前两个,然后退出。

function RunJobFromQueue
{

    if( $queue.Count -gt 0)

    {
        $cn = $queue.Dequeue()

        $j = Start-Job -name $cn -ScriptBlock {param($x); Start-Sleep -Seconds 10;"output - " + $x} -ArgumentList $cn

        Register-ObjectEvent -InputObject $j -EventName StateChanged -Action {RunJobFromQueue; Unregister-Event $eventsubscriber.SourceIdentifier; Remove-Job $eventsubscriber.SourceIdentifier } | Out-Null
    }

}

$maxConcurrentJobs = 2
$jobInput = "test1", "test2", "test3", "test4", "test5", "test6"
$queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) )
foreach($item in $jobInput) {$queue.Enqueue($item)}

for( $i = 0; $i -lt $maxConcurrentJobs; $i++){RunJobFromQueue}

【问题讨论】:

    标签: powershell powershell-2.0 powershell-3.0


    【解决方案1】:

    在我看来:它在脚本中失败是因为:

    • 您启动脚本,在脚本范围内定义函数和变量
    • 脚本在定义 2 个初始作业后退出
    • 作业完成,已注册的操作运行,但您的函数对其不可见(在脚本范围内定义)因此失败。

    解决/解决它的两个选项:

    • 在全局范围内定义 RunJobFromQueue 函数 (function Global:RunJobFromQueue, $global:queue)
    • 点源脚本 (. .\YourScript.ps1)

    这可以很好地交互,因为在这种情况下,您在全局范围内定义函数/变量,所以 -Action 可以很好地找到它们。

    【讨论】: