Author Posts

November 23, 2015 at 2:31 am

Hi,
so i've been trying to create my first GUI. For this question i've made a testcase. I hava an inputfield, if this -ieq "k" then first print "ok" then change it to "lets go". At the moment, it only shows Lets go.

$WPFbutton.Add_Click({
    if($WPFtextBox.Text -ieq "k"){
     $WPFlabel.Content = "ok"
      Write-host "Updating Window"
      sleep 5        
     $WPFlabel.Content = "lets go"
     Write-host "Updating Window 2"
    }
})

Does anyone had an example? Or a suggestion? I"ve been googeling but can't find it.

November 23, 2015 at 3:42 am

Does this do the trick?

$WPFbutton.Add_Click({
    if($WPFtextBox.Text -ieq "k"){
     $WPFlabel.Content = "ok"
     $WPFlabel.Refresh()
      Write-host "Updating Window"
      sleep 5        
     $WPFlabel.Content = "lets go"
     $WPFlabel.Refresh()
     Write-host "Updating Window 2"
    }
})

November 23, 2015 at 5:15 am

Hi Steven,

No sadly not. I tried that before.
I keep getting the following error:

Updating Window
Method invocation failed because [System.Windows.Controls.Label] does not contain a method named 'Refresh'.
At C:\Users\9081059\AppData\Local\Temp\dc3c8e6c-4353-4d63-8fff-2d6e22b930bc.ps1:88 char:6
+      $WPFlabel.Refresh()
+      ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

November 23, 2015 at 5:23 am

Can you send me your full code? If not, try using .Refresh() against the form itself.

November 23, 2015 at 6:19 am

Sure, no problem

$inputXML = @"

    
        
            
                
                
            
        

        
            
                
            
        
        
        
        

        
            
                
                    
                    
                    
                    
                
            
        
        
        
            
                
            
        
        
        
        
        
    
 
"@       
 
$inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N'  -replace '^

$Form.Refresh() results in :

Method invocation failed because [System.Windows.Window] does not contain a met
hod named 'Refresh'.
At line:90 char:6
+      $Form.Refresh()
+      ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

November 23, 2015 at 6:21 am

Does seem the have problem posting the code here.
So i pasted it in pastebin : http://pastebin.com/Npbi1U6h

November 23, 2015 at 7:13 am

Care to share your code πŸ™‚ ? cause no mather where i place InvalidateVisual()
$form.InvalidateVisual() or on the label, the results stays the same :'(

November 25, 2015 at 2:02 am

Anyone else has an idea?

November 25, 2015 at 2:22 am

Have you nanaged to get a WPF label to refresh in C#? it should be a matter of copying the method from there really. Very busy day in the office but I'm curious and will investigate later if I have time

November 25, 2015 at 6:06 am

You are likely running into a common issue with PowerShell and GUIs. Since PowerShell will by default process your code as a single thread. In a lot of situations, the thread gets to processing something else, so the GUI cannot update. Check out this thread on a similar topic with a progress bar. There is also a link there to an innovative solution so that the GUI runs in a separate processing thread.

https://powershell.org/forums/topic/progressbar-example-starting-at-wrong-value/#post-31849

November 25, 2015 at 6:14 am

I don't think you will need to start using multiple threads, as in theory you are only running a method to refresh. If you were running this at the same time as trying to run a command which would take 5 seconds to invoke, I'd probably agree.

Powershell can use whatever assemblies you import, and doesn't lack any of the ability of other languages to actually execute, only how many process it can run simultaneously.

could you please upload your code to pastebin again? I have some free time this afternoon.

Also, in my WinForms, I dot this in certain places, which did fix some issues powershell had with carrying out events:

[System.Windows.Forms.Application]::DoEvents() 

WPF may require something else. As I said, if you can upload again, I will have a look.

November 25, 2015 at 6:28 am

I will be interested to see what Steven finds, but I can say for sure that I have seen this issue particularly with the start-sleep cmdlet since start-sleep keeps the thread from processing anything while it's sleeping. I will also say that I don't usually see this issue with labels. It's usually more complex form controls that I have seen this on, like progress bars.

November 26, 2015 at 12:55 am

I have created a new GUI just for testing purposes.
It only has one button and a label that has to change twices.
If we get this working, i can build my full GUI again.

My application that i needed to make is done by creating a GUI typing out every item of the layout (HTML style).
But i hope we get this working so i can use Visual Studio to create my interfaces, it will save a lot of time.

Anyway , the pastebin : http://pastebin.com/TjWEigZ8

And thanks again for having a look

November 26, 2015 at 1:16 am

$WPFbutton.Add_Click({

	$WPFlabel1.Content = " "    
    $WPFlabel1."Getting data from AD..."
    $WPFlabel1.InvalidateVisual()
    Write-host "Updating Window"
    sleep 3
    $WPFlabel1.Content = "Succes, show results, lets go!"
    $WPFlabel1.InvalidateVisual()
    Write-host "Updating Window 2"
    
})

That works for me πŸ™‚

November 26, 2015 at 1:27 am

Really?

I tried that before, it didn't work :/
I tried it again now, still doesn't work.

Name Value
—- —–
PSVersion 5.0.10514.6
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 10.0.10514.6
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3

November 26, 2015 at 2:13 am

It's only updating once so far, which is once the method has executed.

There are ways you can allow the label to update mid method execution, but you'd need to try to translate from C#
Update WPF UI During Method Execution

To be honest, If I were you, I'd use WinForms. it's tried and tested far more than WPF, and VERY easily used in PowerShell.

I'd try translating yourself, I want to give it a go myself too!

November 26, 2015 at 2:32 am

Yeah i created my first GUI now with WinForms. Just is a pitty that you can't "draw" your layout like WPF. But it will have to do i suppose.

Its not that i'm unwilling but i'm new to Powershell, if i've got to learn C# too, it might be a bit too much. I want to focus my time on Powershell πŸ™‚

November 26, 2015 at 3:10 am

I was where you were 6 months ago. Once I learnt how to use Powershell syntax inside out (by doing massive complex projects in my spare time). I started on C# and it's opened up a whole other side of Powershell, namely because you can interact with .NET better.

Good luck πŸ™‚

I'm actually looking at getting that method to run in powershell, so I'll let you know if I get it working.

November 26, 2015 at 3:41 am

I might not be thΓ‘t talented πŸ™‚
What projects did you work on ?

these are things that i worked on http://pastebin.com/cJRuXnKx

December 7, 2015 at 3:02 am

Well i've been ill for the past week πŸ™
Any luck with this?

February 17, 2017 at 3:50 pm

I took time to port the above mentioned C# solution to native Powershell. It's actually almost identical to what is proposed in Microsoft's Dispatcher.PushFrame Method example.

Function DoEvents()
{
	$frame = New-Object System.Windows.Threading.DispatcherFrame
	[System.Windows.Threading.DispatcherOperationCallback]$CallBack = { $frame.Continue = $false }
	$CurrentDispatcher = [System.Windows.Threading.Dispatcher]::CurrentDispatcher
	$CurrentDispatcher.BeginInvoke("Background", $CallBack, $null)
	[System.Windows.Threading.Dispatcher]::PushFrame($frame)
}

The forum's engine doesn't take XAML, so here's a pastebin working example: http://pastebin.com/0zgaVqKJ

The button initiates a count to 5. Strangely, WPF updates the windows title but fails to update any child control. If you uncomment #DoEvent call it fixes it.

Actually, there's a quicker fix. Instead you can use a one-liner calling this windows' dispatches with an empty action:

$Window.Dispatcher.Invoke("Background", [action]{})

To be honest I don't fully understand the coding esoterics behind it, the C# equivalents of these techniques are discussed here and the comments are ambiguous, some claim one solution is safer the others say the opposite. Go figure. But in my tests they both work and they both quirk. Sometimes they lag and fail to flush the event buffer in time.

February 17, 2017 at 10:03 pm

I took time to port the above mentioned C# solution to native Powershell. It's actually almost identical to what is proposed in Microsoft's Dispatcher.PushFrame Method example.

Function DoEvents()
{
	$frame = New-Object System.Windows.Threading.DispatcherFrame
	[System.Windows.Threading.DispatcherOperationCallback]$CallBack = { $frame.Continue = $false }
	$CurrentDispatcher = [System.Windows.Threading.Dispatcher]::CurrentDispatcher
	$CurrentDispatcher.BeginInvoke("Background", $CallBack, $null)
	[System.Windows.Threading.Dispatcher]::PushFrame($frame)
}

The forum's engine doesn't take XAML, so here's a pastebin working example: http://pastebin.com/0zgaVqKJ

The button initiates a count to 5. Strangely, WPF updates the windows title but fails to update any child control. If you uncomment #DoEvent call it fixes it.

Actually, there's a quicker fix. Instead you can use this one-liner calling the windows' dispatches with an empty action:

$Window.Dispatcher.Invoke("Background", [action]{})

To be honest I don't fully understand the coding esoterics behind it, the C# equivalents of these techniques are discussed here and the comments are ambiguous, some claim one solution is safer the others say the opposite. Go figure. But in my tests they both work and they both quirk. Sometimes they lag and fail to flush the event buffer in time.