Powershell $ button.add_click执行add_click块内的整个代码

时间:2017-06-05 11:55:37

标签: wpf powershell event-handling

我是WPF新手和使用PowerShell的事件处理,我想要实现的是点击一个按钮,进度条应显示在0-100之间。但是当我运行下面的代码时,它会计算add_click块中的整个代码,它只显示循环中的最后一次迭代。 我知道也许这是一个愚蠢的解决方案,但我确实需要一些帮助。

$syncHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"         
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)

$psCmd = [PowerShell]::Create().AddScript({   
    $XamlPath="C:\Forms\MyFormsv1.xaml" 
    $inputXML = Get-Content -Path $XamlPath
    [xml]$Global:xmlWPF = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N'  -replace '^<Win.*', '<Window'

    #Add WPF and Windows Forms assemblies
    try{
    Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
    } catch {
    Throw “Failed to load Windows Presentation Framework assemblies.”
    }


    $syncHash.Window=[Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))

    [xml]$XAML = $xmlWPF

    $xmlWPF.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
    $Global:synchash.Add($_.Name,$synchash.Window.FindName($_.Name) )}

    function tool1_progress{
        $var1=50
        for($index=1 ; $index -le $var1; $index++)
        {            
            [int]$tmpProgNum= ($index/$var1) * 100
            $syncHash.tool1_pb.Value= $tmpProgNum
            $syncHash.consoleOutput.Text=$index
            Start-Sleep -Milliseconds 250 
        }
    }
    $syncHash.myButton.add_click({tool1_progress})  
    $syncHash.Window.ShowDialog() | out-null      
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()
  

$ tool1是一个标签。 $ tool1_pb是一个进度条。 $ consoleOutput是一个   文本框。

1 个答案:

答案 0 :(得分:0)

我一直在集成WPF和PowerShell。 This网站对我帮助很大。您无法更新在同一线程上运行的UI,因此您需要使用BeginInvoke()

调用新的运行空间
$psCmd = [PowerShell]::Create().AddScript({   
$Global:uiHash.Error = $Error
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase
$xaml = @"YOURXAMLHERE"
$Global:uiHash.Window=[Windows.Markup.XamlReader]::Parse($xaml )

[xml]$XAML = $xaml
    $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
    $Global:uihash.Add($_.Name,$uihash.Window.FindName($_.Name) )}
$Global:uiHash.Window.ShowDialog() | out-null
})
$psCmd.Runspace = $newRunspace
$handle = $psCmd.BeginInvoke()

然后,为了更新您需要的内容,您将使用Window.Dispatcher.Invoke

$Global:uiHash.Window.Dispatcher.Invoke([action]{$Global:uiHash.Window.Title = "MyWindowTitle"},"Normal")

修改

$Global:uiHash.Button1.Add_Click(tool1_progress)

编辑

投入您的XML,这将有效。您必须在另一个之上创建另一个运行空间,以便不断更新文本框和进度条。请注意,synchash必须是$Global:synchash。功能由this post.

提供
$Global:syncHash = [hashtable]::Synchronized(@{})
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"         
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)

$psCmd = [PowerShell]::Create().AddScript({   
$XamlPath="C:\Forms\MyFormsv1.xaml" 
$inputXML = @"YOURXMLHERE"@
[xml]$Global:xmlWPF = $inputXML 

#Add WPF and Windows Forms assemblies
try{
Add-Type -AssemblyName PresentationCore,PresentationFramework,WindowsBase,system.windows.forms
} catch {
Throw “Failed to load Windows Presentation Framework assemblies.”
}


$Global:syncHash.Window=[Windows.Markup.XamlReader]::Load((new-object System.Xml.XmlNodeReader $xmlWPF))

[xml]$XAML = $xmlWPF

$xmlWPF.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | %{
$Global:synchash.Add($_.Name,$Global:syncHash.Window.FindName($_.Name) )}

function Start-Runspace{
param($scriptblock)
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = "STA"
$newRunspace.ThreadOptions = "ReuseThread"         
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable("SyncHash",$global:synchash)
$psCmd = [PowerShell]::Create().AddScript($ScriptBlock)
$psCmd.Runspace = $newRunspace
$psCMD.BeginInvoke()
}

   $SB = { 
    $var1=50
    for($index=1 ; $index -le $var1; $index++)
    {            
        [int]$tmpProgNum= ($index/$var1) * 100
        $Global:syncHash.Window.Dispatcher.Invoke([action]{$Global:Synchash.tool1_pb.value = "$tmpprognum"},"Normal")
        $Global:syncHash.Window.Dispatcher.Invoke([action]{$Global:Synchash.consoleoutput.text = "$index"},"Normal")
        Start-Sleep -Milliseconds 250 

    }

}


$Global:syncHash.myButton.add_click({Start-Runspace $SB})  
$Global:syncHash.Window.ShowDialog() | out-null      
})
$psCmd.Runspace = $newRunspace
$data = $psCmd.BeginInvoke()
start-sleep -Milliseconds 300