繁体   English   中英

powershell中按钮事件的运行空间

[英]Runspace for button event in powershell

带有单独运行空间的 $syncHash 按钮事件

不确定这是否是重复的,在网上检查过,并与我发现的一起工作,使用 Boe Prox 的解决方案,该解决方案来自另一篇 StackOverflow 文章引用( https://stackoverflow.com/a/15502286/1546559 ),但在他的,他正在通过在线程内运行的函数从命令行/powershell 窗口进行更新。 我正在从一个按钮运行一个事件,在一个线程内部并尝试为单击事件运行一个单独的线程。 在线程之外,该事件工作正常,但在内部,它根本不起作用..我做错了什么? PS。 我发现另一个博客引用了 Boe Prox 的工作( https://www.foxdeploy.com/blog/part-v-powershell-guis-responsive-apps-with-progress-bars.html ),构建了另一个多线程应用程序,但是几乎相同的概念,通过放置在单独线程内的 powershell commandlet/function 更新窗口。

$push.Add_Click{
    $newRunspace =[runspacefactory]::CreateRunspace()
    $newRunspace.ApartmentState = "STA"
    $newRunspace.ThreadOptions = "ReuseThread"         
    $newRunspace.Open()
    $newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)
    $powershell = [powershell]::Create().AddScript({           
        $choice = $comboBox.SelectedItem
        # $drive = Get-Location
        if(!(Test-Path -PathType Container -Path "L:\$choice"))
        {
    #        New-Item -ItemType "container" -Path . -Name $choice
            New-Item -ItemType "Directory" -Path . -Name $choice
        }

    #        $folder = $_
            # Where is it being stored at?
            [System.IO.File]::ReadLines("Y:\$choice\IPs.txt") | foreach {
                ping -a -n 2 -w 2000 $_ | Out-Null
                Test-Connection -Count 2 -TimeToLive 2 $_ | Out-Null

                if($?)
                {
                   RoboCopy /Log:"L:\$folder\$_.log" $source \\$_\c$\tools
                   RoboCopy /Log+:"L:\$folder\$folder-MovementLogs.log" $source \\$_\c$\tools
                   Start-Process "P:\psexec.exe" -ArgumentList "\\$_ -d -e -h -s cmd /c reg import C:\tools\dump.reg"
                   # Copy-Item -LiteralPath Y:\* -Destination \\$_\c$\tools
                   $listBox.Items.Add($_)
                }
            }
    })
    $powershell.Runspace = $newRunspace
    $powershell.BeginInvoke()

}

您可以将其用作您想要做的事情的蓝图,重要的是运行空间无法看到您表单的控件。 如果您希望运行空间与控件交互,则必须将它们传递给它,例如通过SessionStateProxy.SetVariable(...)或作为.AddParameters(..)的参数。

using namespace System.Windows.Forms
using namespace System.Drawing
using namespace System.Management.Automation.Runspaces

Add-Type -AssemblyName System.Windows.Forms

[Application]::EnableVisualStyles()

try {
    $form = [Form]@{
        StartPosition   = 'CenterScreen'
        Text            = 'Test'
        WindowState     = 'Normal'
        MaximizeBox     = $false
        ClientSize      = [Size]::new(200, 380)
        FormBorderStyle = 'Fixed3d'
    }

    $listBox = [ListBox]@{
        Name       = 'myListBox'
        Location   = [Point]::new(10, 10)
        ClientSize = [Size]::new(180, 300)
    }
    $form.Controls.Add($listBox)

    $runBtn = [Button]@{
        Location   = [Point]::new(10, $listBox.ClientSize.Height + 30)
        ClientSize = [Size]::new(90, 35)
        Text       = 'Click Me'
    }
    $runBtn.Add_Click({
        $resetBtn.Enabled = $true

        if($status['AsyncResult'].IsCompleted -eq $false) {
            # we assume it's running
            $status['Instance'].Stop()
            $this.Text = 'Continue!'
            return # end the event here
        }

        $this.Text = 'Stop!'
        $status['Instance']    = $instance
        $status['AsyncResult'] = $instance.BeginInvoke()
    })
    $form.Controls.Add($runBtn)

    $resetBtn =  [Button]@{
        Location   = [Point]::new($runBtn.ClientSize.Width + 15, $listBox.ClientSize.Height + 30)
        ClientSize = [Size]::new(90, 35)
        Text       = 'Reset'
        Enabled    = $false
    }
    $resetBtn.Add_Click({
        if($status['AsyncResult'].IsCompleted -eq $false) {
            $status['Instance'].Stop()
        }
        $runBtn.Text  = 'Start!'
        $this.Enabled = $false
        $listBox.Items.Clear()
    })
    $form.Controls.Add($resetBtn)

    $status = @{}
    $rs = [runspacefactory]::CreateRunspace([initialsessionstate]::CreateDefault2())
    $rs.ApartmentState = [Threading.ApartmentState]::STA
    $rs.ThreadOptions  = [PSThreadOptions]::ReuseThread
    $rs.Open()
    $rs.SessionStateProxy.SetVariable('controls', $form.Controls)
    $instance = [powershell]::Create().AddScript({
        $listBox = $controls.Find('myListBox', $false)[0]
        $ran  = [random]::new()

        while($true) {
            Start-Sleep 1
            $listBox.Items.Add($ran.Next())
        }
    })
    $instance.Runspace = $rs
    $form.Add_Shown({ $this.Activate() })
    $form.ShowDialog()
}
finally {
    ($form, $instance, $rs).ForEach('Dispose')
}

演示

演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM