Display output of the CMD in real time inside TextBox

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 5 years and 6 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

Re: Display output of the CMD in real time inside TextBox

Post by ALIENQuake »

Well, here is another attempt:

- $count is an index of element from array of processes
- when the current process has exited i simply do: $script:count++
- SynchronizingObject has to be passed via parameter to the function
- it's possible to send input to the current app
- readinput process is readinput.exe from below code

It seems to behave exactly as I wanted. Let me integrate it and see final results. Amazing support by jvierra, thank you!

code for readinput.exe

Code: Select all

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace readinput {
    class Program {
        static void Main( string[] args ) {
            Console.WriteLine("Read input");
            Console.WriteLine("");
            var s = Console.ReadLine();
            Console.WriteLine("Out from app:");
            Console.WriteLine(s);
            //Console.ReadKey();
        }
    }
}
Code for form:

Code: Select all

$code = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
'@
Add-Type -MemberDefinition $code -Name Win32SetParent -Namespace Win32Functions

function Run-Process ($count, $sync) {
	
	$script:p = [System.Diagnostics.Process]::New() # has to be $script: because of buttonSendInput_Click > $p.StandardInput.WriteLin
	
	$p.add_Exited({
			#[System.Windows.Forms.MessageBox]::Show('Process Exited!')
			$script:count++
			if ($script:count -lt $dataP.count) {
				Run-Process -count $script:count -sync $form1
			}
		})
	
	$p.add_OutputDataReceived({
			$textbox2.Lines += $_.Data
			
			$textbox2.Select($textbox2.Text.Length, 0)
			$textbox2.ScrollToCaret()
		})
	
	$p.StartInfo.RedirectStandardOutput = $true
	$p.StartInfo.RedirectStandardError = $true
	$p.StartInfo.RedirectStandardInput = $true
	$p.StartInfo.UseShellExecute = $false
	#$p.StartInfo.CreateNoWindow = $true
	$p.StartInfo.FileName = $dataP[$count]
	$p.StartInfo.Arguments = '-n 3 google.com'
	$p.EnableRaisingEvents = $true
	$p.SynchronizingObject = $sync
	
	if ($script:count -lt $dataP.count) {
		$p.Start()
		do {
			Start-Sleep -Milliseconds 50
		} until ($p.MainWindowHandle)
		
		$p.BeginOutputReadLine()
		
		[Win32Functions.Win32SetParent]::SetParent($p.MainWindowHandle, $textbox1.Handle)
	}
}

$form1_Load = {
	#TODO: Initialize Form Controls here
	$global:dataP = 'ping', 'readinput', 'ping'
	$script:count = 0
}

$form1_FormClosing = [System.Windows.Forms.FormClosingEventHandler]{
	#Event Argument: $_ = [System.Windows.Forms.FormClosingEventArgs]
	Write-Host Form closing
}

$form1_FormClosed = [System.Windows.Forms.FormClosedEventHandler]{
	#Event Argument: $_ = [System.Windows.Forms.FormClosedEventArgs]
	Write-Host Form Closed
}

$form1_ParentChanged = {
	Write-Host Parent
}

$buttonRunProcess_Click = {
	#TODO: Place custom script here
	Run-Process -count $script:count -sync $form1
}


$buttonSendInput_Click = {
	#TODO: Place custom script here
	$p.StandardInput.WriteLine($textboxInput.Text)
	$p.StandardInput.WriteLine("`n") # simulate 'ENTER'
}
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Display output of the CMD in real time inside TextBox

Post by jvierra »

Synchronizing object must be the form:
$p.SynchronizingObject = $form1

"SetParent" is only used if you want to display the process window within a form object. If so then position and an location tracking (OnMove) must be implemented for this to display correctly.
User avatar
ALIENQuake
Posts: 112
Last visit: Mon Jan 29, 2024 7:35 am
Has voted: 4 times

Re: Display output of the CMD in real time inside TextBox

Post by ALIENQuake »

jvierra wrote: Wed Sep 05, 2018 11:16 am Synchronizing object must be the form:
$p.SynchronizingObject = $form1
It is: it's passed via -sync $form1 parameter
jvierra wrote: Wed Sep 05, 2018 11:16 am "SetParent" is only used if you want to display the process window within a form object. If so then position and an location tracking (OnMove) must be implemented for this to display correctly.
Yep, it's nice to see process windows inside application window, not flying around whole desktop
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Display output of the CMD in real time inside TextBox

Post by jvierra »

You redirected errors but did not provide:

$p.add_ErrorDataReceived({ .. })
$p.BeginErrorReadLine()


If you are redirecting all output then the process Window is unnecessary. Just set "CreateNoWindow" and it will not be visible.
This topic is 5 years and 6 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