首页 > 解决方案 > 从 Start-Job (Powershell) 更新 winforms GUI

问题描述

我正在尝试在 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} | {2}GB of {3}GB | {4}MB of {5}MB | {6}% Complete (Average: {7}Mbps)" -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: {0}MB of {1}MB" -f [Math]::Round($MBCopied, 2), [Math]::Round($MBTotal, 2))
            $RobocopyGBProgress.Text = ("Data: {0}GB of {1}GB" -f [Math]::Round($GBCopied, 2), [Math]::Round($GBTotal, 2))
            $RobocopyPcntProgress.Text = ("Percentage: {0}%" -f [Math]::Round($Percentage, 2))
            $RobocopySpeed.text = ("Speed: {0}Mbps" -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: {0}MB of {1}MB" -f [Math]::Round($MBCopied, 2), [Math]::Round($MBTotal, 2))
        $RobocopyGBProgress.Text = ("Data: {0}GB of {1}GB" -f [Math]::Round($GBCopied, 2), [Math]::Round($GBTotal, 2))
        $RobocopyPcntProgress.Text = ("Percentage: {0}%" -f [Math]::Round($Percentage, 2))
        $RobocopySpeed.text = ("Speed: {0}Mbps" -f [Math]::Round($script:avgSpeed, 2))
    }

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

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

标签: powershellwinformsuser-interfacerobocopystart-job

解决方案


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

大文件复制期间的进度(复制项目和写入进度?)

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


推荐阅读