【问题标题】:Powershell GUI, Progress Bar, and Hash TablesPowershell GUI、进度条和哈希表
【发布时间】:2014-07-05 04:12:06
【问题描述】:

我正在处理的部分脚本采用指定的用户名,在活动目录中搜索以该用户名命名的计算机,对它们执行 ping 操作,然后将在线计算机添加到阵列中以供以后使用。我想在脚本的 ping 部分添加一个进度条,但我遇到了问题。如果我在 ping 循环之前调用它,我必须呈现进度条的表单会冻结脚本的执行。

这是进度条的代码(非常基本):

#Progress Bar
$objFormPBar = New-Object System.Windows.Forms.Form
$objFormPBar.Text = "Loading"
$objFormPBar.Size = New-Object System.Drawing.Size(200,100) 
$objFormPBar.StartPosition = "CenterScreen"
$objFormPBar.Topmost = $True
$objFormPBar.Icon = $Icon

$progressBar = New-Object System.Windows.Forms.ProgressBar
$progressBar.Size = New-Object System.Drawing.Size(175,20)
$progressBar.Location = New-Object System.Drawing.Size(5, 20)
$progressBar.Minimum = 0
$progressBar.Maximum = 0
$objFormPBar.Controls.Add($progressBar)

这是我试图显示它的地方,这样会暂停脚本的执行(从点击处理函数内部调用,因此是全局变量):

$global:progressBar.Maximum = $computers.count
$global:objFormPBar.Add_Shown({$objFormPBar.Activate()})
[void] $global:objFormPBar.ShowDialog()

Foreach ($computer in $computers) {
    $computer = $computer.trim()
    If(Test-Connection $computer -Count 1) {
        $arrayComputers.add($computer) | Out-Null
    }
    $global:progressBar.Increment(1)
}

$global:objFormPBar.Close()

查看问题,我发现您可以在单独的线程中运行进度条并在两者之间传递变量(请参阅:Marquee Progress Bar freezes in Powershell)。但是,我没有运气让它工作,甚至没有启动另一个线程。我怎样才能让这个进度条和表单一起在另一个线程中运行?

【问题讨论】:

    标签: multithreading powershell


    【解决方案1】:

    为什么不直接使用内置 UI 在 PowerShell 中报告进度?这是对Write-Progress 的单行调用,例如:

    $computers = 1..10 | % {"server$_"}
    $numComputers = $computers.Length
    for ($ndx = 0; $ndx -le $numComputers; $ndx++) {
        $computer = $computers[$ndx].Trim()
        Write-Progress "Testing connection to $computer" -PercentComplete ($ndx/$numComputers * 100)
        #if (Test-Connection $computer -Count 1) {
        #    $arrayComputers.add($computer) | Out-Null
        #}
        Start-Sleep -Seconds 1
    }
    

    顺便说一句,上述方法的主要问题是 ShowDialog() 方法调用在表单关闭之前不会返回。如果您想使用 ShowDialog(),您必须在表单内的事件处理程序的上下文中执行您的逻辑(加载/激活)。另一种选择是使用Show(),但这意味着您必须使用 Application.DoEvents() 在循环中发送消息,以便表单有机会自行更新。

    【讨论】:

    • 哇,这很简单,谢谢。看起来我的计数器没有正确增加,但我想我可以解决这个问题。我不写信给控制台的原因只是为了让事情看起来更好。整个过程将通过 GUI 完成,而不是控制台。
    • 如果您不使用计数器/ndx 递增的for 循环,那么请小心使用$counter++,因为这不会“输出”结果。要获得增量和输出,请使用($counter++)
    猜你喜欢
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 2020-04-17
    • 2019-04-27
    • 2021-05-29
    • 2013-07-19
    相关资源
    最近更新 更多