从 Start-Job (Powershell) 更新 winforms GUI

Posted

技术标签:

【中文标题】从 Start-Job (Powershell) 更新 winforms GUI【英文标题】:Update winforms GUI from Start-Job (Powershell) 【发布时间】:2021-11-22 18:51:30 【问题描述】:

我正在尝试在 powershell 中创建自定义 Robocopy 状态 GUI,这是我的基本代码。

$script:Robocopy = Start-Process -FilePath robocopy.exe -ArgumentList $ArgumentList -Verbose -PassThru -NoNewWindow;

$RCStatus = Start-Job -Name RCLOOP -ArgumentList $Robocopy, $ReportGap, $RobocopyLogPath, $RegexBytes, $RobocopyFileProgress, $RobocopyMBProgress, $RobocopyGBProgress, $RobocopyPcntProgress, $RobocopySpeed 
        param ($Robocopy, $ReportGap, $RobocopyLogPath, $RegexBytes, $RobocopyFileProgress, $RobocopyMBProgress, $RobocopyGBProgress, $RobocopyPcntProgress, $RobocopySpeed)
        $iterations = 0
        [array]$avgSpeedarray = @()
        while (!$Robocopy.HasExited) 
            Start-Sleep -Milliseconds $ReportGap;
            $BytesCopied = 0;
            $LogContent = Get-Content -Path $RobocopyLogPath;
            $BytesCopied = [Regex]::Matches($LogContent, $RegexBytes) | ForEach-Object -Process  $BytesCopied += $_.Value;  -End  $BytesCopied; ;
            $global:MBCopied = ($BytesCopied / 1048576)
            $global:GBCopied = ($BytesCopied / 1073741824)
            $script:CopiedFileCount = $LogContent.Count - 1;
            $iterations++
        
            if ($iterations % 2 -eq 1) 
                $M = $MBCopied
            
            else 
                $B = $MBCopied
                $script:TSpeed = ($B - $M) * 8
                $avgSpeedarray += $script:TSpeed
                if ($avgSpeedarray.count -gt 4) 
                    $script:avgSpeed = (($avgSpeedarray[-1..-10] | Measure-Object -sum).sum) / 10
                    if ($avgSpeedarray.count -gt 19) 
                        $keep = $avgSpeedarray[-1..-9]
                        $avgSpeedarray = @()
                        $avgSpeedarray += $keep
                    
                
            
            if ($iterations % 20 -eq 0) 
                $keepAwake
            
            Write-Verbose -Message ('MB copied: 0' -f $MBCopied);
            Write-Verbose -Message ('Files copied: 0' -f $LogContent.Count);
            $Percentage = 0;
            if ($BytesCopied -gt 0) 
                $Percentage = (($BytesCopied / $BytesTotal) * 100)
            
            #Write-Progress -Activity Robocopy -Status ("Copied 0 of 1 | 2GB of 3GB | 4MB of 5MB | 6% Complete (Average: 7Mbps)" -f $CopiedFileCount, $TotalFileCount, [Math]::Round($GBCopied, 2), [Math]::Round($GBTotal, 2), [Math]::Round($MBCopied, 2), [Math]::Round($MBTotal), [Math]::Round($Percentage, 2), [Math]::Round($script:avgSpeed,2)) -PercentComplete $Percentage
            $RobocopyFileProgress.Text = ("Files: 0 of 1" -f $CopiedFileCount, $TotalFileCount)
            $RobocopyMBProgress.Text = ("Data: 0MB of 1MB" -f [Math]::Round($MBCopied, 2), [Math]::Round($MBTotal, 2))
            $RobocopyGBProgress.Text = ("Data: 0GB of 1GB" -f [Math]::Round($GBCopied, 2), [Math]::Round($GBTotal, 2))
            $RobocopyPcntProgress.Text = ("Percentage: 0%" -f [Math]::Round($Percentage, 2))
            $RobocopySpeed.text = ("Speed: 0Mbps" -f [Math]::Round($script:avgSpeed, 2))
        
    

    $RobocopyProgressGUI.Show()

    #endregion Progress loop
    Register-ObjectEvent -InputObject $script:Robocopy -EventName OutputDataReceived -SourceIdentifier 'RobocopyStatus' -Action 
        $RobocopyFileProgress.Text = ("Files: 0 of 1" -f $CopiedFileCount, $TotalFileCount)
        $RobocopyMBProgress.Text = ("Data: 0MB of 1MB" -f [Math]::Round($MBCopied, 2), [Math]::Round($MBTotal, 2))
        $RobocopyGBProgress.Text = ("Data: 0GB of 1GB" -f [Math]::Round($GBCopied, 2), [Math]::Round($GBTotal, 2))
        $RobocopyPcntProgress.Text = ("Percentage: 0%" -f [Math]::Round($Percentage, 2))
        $RobocopySpeed.text = ("Speed: 0Mbps" -f [Math]::Round($script:avgSpeed, 2))
    

我的一个问题是我的表单只是打开和关闭而没有任何脚本告诉它关闭,另一个是上面输出的所有代码都是关于作业的信息,而不是作业输出的信息。

我知道我的代码非常冗长,它是故障排除过程的一部分,我知道 C# 是一个更好的选择,但我正在尝试在 powershell 中实现它,因为我在 C# 中不是很好。任何帮助或建议都会很棒。如果您需要我的程序中我错过的任何其他代码,请告诉我,我会提供它

【问题讨论】:

【参考方案1】:

这是一个如何在 powershell 中使用带有进度条的 robocopy 的示例。我改编了一个现有的答案,然后根据我在使用它时发现的一些问题进一步完善它。希望对您有所帮助。

Progress during large file copy (Copy-Item & Write-Progress?)

如果你想做一个 GUI,我还建议使用 WPF/xaml 而不是 winforms。 Winforms 在 PowerShell 中似乎有些不稳定。此外,您可以在 Visual Studio 中创建您的 xaml,然后复制/粘贴。这也允许您将可视化与功能分开。

【讨论】:

谢谢你的建议,我试试看! 你能让这个工作吗?

以上是关于从 Start-Job (Powershell) 更新 winforms GUI的主要内容,如果未能解决你的问题,请参考以下文章

Powershell - 如何为 Start-Job 预先评估脚本块中的变量

PowerShell 并行执行任务

在后台运行 powershell 命令

Powershell构建步骤,火灾和忘记?

用于提高状态行性能的 Powershell 作业

powershell“无法使用指定的命名参数解析参数集”