Embed a console in winform app

Product: PowerShell Universal
Version: 1.4.6

Hi guys !

Since 2 years now that I can’t manage to have a fully responsive winform app that can stream the output of a console (cmd.exe) without freezing the gui.

My goal is to embed the cmd.exe (or any shell) to winform using Powershell. The idea is to have two box. One for the output, the second for the input.

This script stream the output of cmd.exe but can’t work with winform due to GUI freezing…

$cmdProcess = New-Object System.Diagnostics.Process
$cmdProcess.StartInfo.FileName = “cmd.exe”
$cmdProcess.StartInfo.UseShellExecute = $false
$cmdProcess.StartInfo.RedirectStandardOutput = $true
$cmdProcess.StartInfo.RedirectStandardError = $true
$cmdProcess.StartInfo.CreateNoWindow = $true
$cmdProcess.Start() | Out-Null
$ProcessID = $cmdProcess.Id

Write-Host “ID : $ProcessID” -ForegroundColor DarkGreen

while (-not $cmdProcess.HasExited) {
$output = $cmdProcess.StandardOutput.ReadLine()
if ($output) {
Write-Output $output
}
}

I know that background/multi-threading task allow to have a responsive GUI but two issues remains :

  • Data lost : the data in backgrounds jobs are lost / can’t dialogue with you’re main process

  • Jobs state : Even if you have the data, the background job can’t stream synchronously the output because the job state is never finished.

My attempt with ThreadJob :

$Global:cmdProcess = New-Object System.Diagnostics.Process
$Global:cmdProcess.StartInfo.FileName = “cmd.exe”
$Global:cmdProcess.StartInfo.UseShellExecute = $false
$Global:cmdProcess.StartInfo.RedirectStandardOutput = $true
$Global:cmdProcess.StartInfo.RedirectStandardError = $true
$Global:cmdProcess.StartInfo.CreateNoWindow = $true
$Global:cmdProcess.Start() | Out-Null
$ProcessID = $Global:cmdProcess.Id

Write-Host “ID : $ProcessID” -ForegroundColor DarkGreen

Start-ThreadJob -Name “test” -ScriptBlock {
while (-not $Global:cmdProcess.HasExited) {
$Global:output = $Global:cmdProcess.StandardOutput.ReadLine()
if ($Global:output) {
Write-Output $Global:output
}
} } -StreamingHost $Host

Receive-Job -Name “test”

I hope you guys can help me. (English not my native language)