Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bring Powershell-Console to front from WinForms

im trying to bring my powershell console to front, even if it is minimized. I found following code:

function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '

  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd) 
}
Show-Process -Process (Get-Process -Id $pid) 

It works fine, but when i call the function from a Button Click event, the console wont show. What is the Problem? Is there a way to bring the powershell Console to front when using a WinForms GUI?

Here is the example GUI Code:

function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '

  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd) 
}

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '446,266'
$Form.text                       = "Form"
$Form.TopMost                    = $false

$Button1                         = New-Object system.Windows.Forms.Button
$Button1.text                    = "button"
$Button1.width                   = 60
$Button1.height                  = 30
$Button1.location                = New-Object System.Drawing.Point(75,29)
$Button1.Font                    = 'Microsoft Sans Serif,10'

$Button1.Add_Click({
    Show-Process -Process (Get-Process -Id $pid) 
})

$Form.controls.AddRange(@($Button1))

[void]$Form.ShowDialog()
like image 719
Evilcat Avatar asked Nov 03 '18 04:11

Evilcat


1 Answers

Thanks to @iRon's answer, i was able to figure it out, how i want it. For anyone curious, the problem is, you only can get the consoles MainwindowHandle as long as ShowDialog wasn't called. So i save the console Handle in a variable and i use the Form_Shown event to get the Form WindowHandle, since Form_Load still returns the Console Handle.

$sig = '
[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);'
$type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
[IntPtr]$handleConsole = (Get-Process -Id $pid).MainWindowHandle
[void]$type::ShowWindowAsync($handleConsole, 4);[void]$type::SetForegroundWindow($handleConsole)

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '446,266'
$Form.text                       = "Form"
$Form.TopMost                    = $false

$Form.Add_Shown({
 $global:handleForm = (Get-Process -Id $pid).MainWindowHandle
})

$Button1                         = New-Object system.Windows.Forms.Button
$Button1.text                    = "Clone ad-USer"
$Button1.width                   = 60
$Button1.height                  = 30
$Button1.location                = New-Object System.Drawing.Point(75,29)
$Button1.Font                    = 'Microsoft Sans Serif,10'

$Button1.Add_Click({
    [void]$type::ShowWindowAsync($handleConsole, 4);[void]$type::SetForegroundWindow($handleConsole)
    Read-Host -Prompt "Please Enter a Value"
    [void]$type::ShowWindowAsync($global:handleForm, 4);[void]$type::SetForegroundWindow($global:handleForm)
})

$Form.controls.AddRange(@($Button1))

[void]$Form.ShowDialog()

Now, if i press the Button, to console pops up in front. After the User enter something into the Console, the Form comes to front again.

like image 186
Evilcat Avatar answered Sep 30 '22 16:09

Evilcat