如何在主GUI窗口中显示powershell作业的输出?

时间:2015-09-03 23:16:44

标签: multithreading user-interface powershell jobs

请参阅下面的更新。

在查看多个网站和论坛后,我决定发帖提问,因为我无法解决这个问题。

我有一个使用WinForms创建GUI窗口的powershell脚本(如下所示)。右侧是在所选复选框工作时显示输出。它可以工作,除了窗口冻结和\或变成"没有响应"。我一直在寻找变化的东西,所以他们在工作中运行,除了我不能找出正确的语法来运行工作,并且还显示它在列表框中做了什么。我理解工作是单独的PowerShell流程,但是有一种方法可以在工作正在运行时显示它当前正在做什么吗?

我不确定要发布的代码部分,因为它适用于整个事情,但这里是目前的代码片段......

$handler_button1_Click= {

    $domain=$TextBox2.Text
    $user=$TextBox3.Text
    $pass=$TextBox4.Text
    $id=$TextBox1.Text

    $listBox1.Items.Clear()    

    if ($checkBox1.Checked -and !$checkBox2.Checked) { uninstall }

    if ($checkBox2.Checked -and $checkBox1.Checked) { $security -eq "y"; uninstall }

    ...

    if ($checkBox7.Checked) { $prog = "Firefox"
                              $appname = $firefox
                              $arguments = " -ms"
                              install }
}

现在我有复选框可以使用ForEach循环卸载一堆软件或安装软件。当我运行所选的框时,我希望它显示当前正在卸载或安装的内容。它完成了它的工作,但在完成所有工作之前我无法看到它做了什么,然后清单就会刷新,并且那里的一切都已经完成。

我尝试将该函数改为变量,然后使用" Start-Job -ScriptBlock"在" checkbox.checked"上面的代码。我尝试以不同的方式将函数包装在Start-Job命令中。我想我已经让它运行了,但我不能说,因为它没有向我展示任何东西。

这需要在Windows 7中运行。

我已在下面附上了GUI的图片。

任何帮助将不胜感激。 感谢。

更新

所以我得到了运行并在其PS窗口中显示输出的工作。尽管如此,Haven还没弄明白如何让它在GUI的列表框中显示输出。

我遇到了将工作目录设置到脚本目录的变量问题。它在主脚本中工作正常,但在放入作业时会抛出一个空的或无效的错误。这是我用来计算这个工作内容的测试脚本......

理想情况下,我想要做的是让脚本中的每个功能都成为一个工作(主GUI功能除外)并且每个功能都有一个" checkbox.checked"上面的部分开始一个工作,它的输出显示在GUI列表框中。

我从实际脚本中复制\粘贴了大部分全局变量。有几个"写主机"应该是" $ listbox1.items.add("")"。我将它们更改为" write-host"所以我在测试时会看到一些输出。

有没有办法让变量可用于其他工作?在将变量列表放入$ updates并手动将文件路径输入$ dir之前,下面的代码不起作用。

$updates = {

$global:scriptpath = $MyInvocation.MyCommand.Path
$global:dir = Split-Path $scriptpath
$global:logfile = "$dir\Apps\log.txt"
$global:ftppath = # REMOVED #
$global:firefox = "install_firefox.exe"
$global:chrome = "install_chrome.msi"
$global:reader = "install_reader.exe"
$global:java32 = "install_java_x32.exe"
$global:java64 = "install_java_x64.exe"
$global:flashie = "install_flash_ie.exe"
$global:flashnonie = "install_flash_nonie.exe"
$global:office = "install_o365.exe"

function updates {

$list = "Flash for IE","Flash for Other Browsers","Java 32-bit","Java 64-bit","Adobe Reader","Firefox","Chrome","Office 365"

ForEach ($prog in $list) {

    Try {

        If ($prog -eq "Flash for IE") {$appname = $flashie}
        If ($prog -eq "Flash for Other Browsers") {$appname = $flashnonie}
        If ($prog -eq "Java 32-bit") {$appname = $java32}
        If ($prog -eq "Java 64-bit") {$appname = $java64}
        If ($prog -eq "Adobe Reader") {$appname = $reader}
        If ($prog -eq "Firefox") {$appname = $firefox}
        If ($prog -eq "Chrome") {$appname = $chrome}
        If ($prog -eq "Office 365") {$appname = $office}

        $filecheck = "$dir\Apps\$appname"

        If(-not(Test-Path -path $filecheck)) {

            write-host " Downloading $($prog) Installer..."
            $File = "$dir\Apps\$appname"
            $ftp = "$ftppath/$appname"
            $webclient = New-Object System.Net.WebClient
            $uri = New-Object System.Uri($ftp)
            $webclient.DownloadFile($uri, $File)

            "   Downloaded $($prog)" >> $logfile

        } # End If

        Else {

            $ftprequest = [System.Net.FtpWebRequest]::Create("$ftppath/$appname")
            $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::GetDateTimestamp
            $response = $ftprequest.GetResponse().StatusDescription
            $tokens = $response.Split(" ")
            $code = $tokens[0]

            $localtime = (Get-Item "$dir\Apps\$appname").LastWriteTimeUtc

            If ($code -eq 213) {

                $tokens = $tokens[1]
                $localtime = "{0:yyyyMMddHHmmss}" -f [datetime]$localtime

                If ($tokens -gt $localtime) {

                    write-host " Updating $($prog) Installer..."
                    $File = "$dir\Apps\$appname"
                    $ftp = "$ftppath/$appname"
                    $webclient = New-Object System.Net.WebClient
                    $uri = New-Object System.Uri($ftp)
                    $webclient.DownloadFile($uri, $File)

                    "   Updated $($prog)" >> $logfile

                } # End If

                Else { $listBox1.Items.Add(" $($prog) skipped.") }

            } # End If

        } # End Else

    } # End Try

    Catch { write-host " ERROR: Couldn't update $($prog)"
            "   Error updating $($prog)" >> $logfile }

} # End ForEach

} # End Function

} # End Variable

Start-Job -Name "Updates" -ScriptBlock {updates} -InitializationScript $updates | Wait-Job | Receive-Job

1 个答案:

答案 0 :(得分:0)

您可以将每个作业分成一个任务,然后在后台使用计时器检查每个作业

If (($JobTask1).State -eq "Running"))
   {
   $Label1.Text = "JobTask1 is Still Running"
   }

另一种选择是使用

Receive-Job $Jobs -Keep

并操纵输出以查找已完成的操作。