Display process output in real time inside TextBox for WPF

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
This topic is 2 years and 2 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked
User avatar
ALIENQuake
Posts: 112
Last visit: Mon Jan 29, 2024 7:35 am
Has voted: 4 times

Display process output in real time inside TextBox for WPF

Post by ALIENQuake »

Hi,

I would like to modernize the look of my app by switching to WPF. I need to recreate "Display output of the CMD in real-time inside TextBox" viewtopic.php?t=12969 but for WPF.

The problem is that WPF threading is completely different and it doesn't have "process.SynchronizingObject/System.ComponentModel.ISynchronizeInvoke" so Dispatcher must be used somehow.

After many strougles, I was able to comeup with this:

Code: Select all

Add-Type -AssemblyName PresentationFramework
$Xaml = New-Object System.Xml.XmlNodeReader([XML]@"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Test" WindowStartupLocation = "CenterScreen" ShowInTaskbar = "True">
    <Grid>
        <TextBox x:Name = "TextBox"/>
    </Grid>
</Window>
"@)

Function Start-Worker {
    $TextBox = $Window.FindName("TextBox")
    $SyncHash = [hashtable]::Synchronized(@{Window = $Window; TextBox = $TextBox})
    $Runspace = [runspacefactory]::CreateRunspace()
    $Runspace.ThreadOptions = "ReuseThread"         
    $Runspace.Open()
    $Runspace.SessionStateProxy.SetVariable("SyncHash", $SyncHash)          
    
    # Problem 1 - UI is lagging
    $Worker = [PowerShell]::Create().AddScript({
        for($Progress=1; $Progress -le 25; $Progress++){
            $SyncHash.Window.Dispatcher.Invoke([action]{$SyncHash.TextBox.AppendText($Progress)}) | Out-Null
        }
    })

    $Worker.Runspace = $Runspace
    $Worker.BeginInvoke()

    # Problem 2, even empty OutputDataReceived will cause crash
    # $Worker = [PowerShell]::Create().AddScript({
    #     $process = New-Object System.Diagnostics.Process
    #     $process.StartInfo.FileName = 'ping.exe'
    #     $process.StartInfo.Arguments = 'google.com -n 3'
    #     $process.StartInfo.UseShellExecute = $false
    #     $process.StartInfo.CreateNoWindow = $true
    #     $process.StartInfo.RedirectStandardInput = $false
    #     $process.StartInfo.RedirectStandardOutput = $true
    #     $process.EnableRaisingEvents = $true

    #     $process.add_OutputDataReceived({
    #         # even empty OutputDataReceived will cause crash
    #         #[System.Console]::WriteLine( $_.Data)
    #         #$SyncHash.Window.Dispatcher.Invoke([action]{$SyncHash.TextBox.AppendText($_.Data)})
    #     })
    
    #     $process.Start() | Out-Null
    #     $process.BeginOutputReadLine()
    # })
    # $Worker.Runspace = $Runspace
    # $Worker.BeginInvoke()

}

$script:Window = [Windows.Markup.XamlReader]::Load($Xaml)
$script:TextBox = $Window.FindName("TextBox")
$Window.Add_Loaded({ Start-Worker })
[Void]$Window.ShowDialog()
The code works but I have 2 problems:
1. UI is lagging
2. Adding OutputDataReceived (even empty) cause crash - no process output can be received

I don't know how to improve solution further. Can someone please take look?
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Display process output in real time inside TextBox for WPF

Post by jvierra »

Works fine for me.
User avatar
ALIENQuake
Posts: 112
Last visit: Mon Jan 29, 2024 7:35 am
Has voted: 4 times

Re: Display process output in real time inside TextBox for WPF

Post by ALIENQuake »

Try to movie window when the code is running. Also, the process_OutputDataReceived will cause crash even if it's empty. So maybe the whole approach is wrong? Do you have any idea about the alternative way of doing this?
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Display process output in real time inside TextBox for WPF

Post by jvierra »

I can move anything, and it still works fine. Perhaps you have context related issues.
This topic is 2 years and 2 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked