2

Given a single-instance desktop application ccTest.exe, how can I use PowerShell (v6 or 7) to run the application in the Normal state if it is already running in Minimized state.

I need access to controls in the main window so it must be in Normal state. Get-Process works to check if the app is running. If not, then launch it with Start-Process and -WindowStyle Normal parameter. But Start-Process does not work if the the single-instance app is already running Minimized.

Due to timing constraints I'd rather not close ccTest.exe if minimized and then launch with Start-Process. Here is the test code.

if (Get-Process | Select MainWindowTitle, ProcessName, Id | where {$_.MainWindowTitle -like "ccTest*"})
{ 
    if Minimized make it Normal
    execute needed function
}
else
{
   start-process "C:\Program Files (x86)\Test\ccTest.exe" -WindowStyle Normal
   execute needed function
}

So how to change State/Style from Minimized to Normal to run the needed function?

cefeg
  • 33
  • 7

1 Answers1

3

This should do the trick.

Add-Type -AssemblyName UIAutomationClient

$MyProcess = Get-Process | where { $_.MainWindowTitle -like "ccTest*" }
if ($null -ne $MyProcess) { 
    # if Minimized make it Normal
    $ae = [System.Windows.Automation.AutomationElement]::FromHandle($MyProcess.MainWindowHandle)
    $wp = $ae.GetCurrentPattern([System.Windows.Automation.WindowPatternIdentifiers]::Pattern)
    if ($wp.Current.WindowVisualState -eq 'Minimized') {
        $wp.SetWindowVisualState('Normal') 
    }
    # execute needed function
}
else {
    start-process "C:\Program Files (x86)\Test\ccTest.exe" -WindowStyle Normal
    # execute needed function
}

References:

Maximize window and bring it in front with powershell

Get window state of another process

Sage Pourpre
  • 9,932
  • 3
  • 27
  • 39
  • Thanks to both of you for your answers. Sage's almost did the job but the in the If (... -eq 'Minimized') statement, True was returned to PowerShell. This must have moved the focus to PowerShell so my function did now work properly. So I added mklement0's code and all worked fine. – cefeg Jan 08 '22 at 20:48
  • Not that familiar with how Stackoverflow works. Is there a way I can reward you both? – cefeg Jan 08 '22 at 20:50
  • 1
    @mklement0 Good points. I updated my answer accordingly. As for your second comment, to activate without changing state, this appear to work fine `$wp.SetWindowVisualState($wp.Current.WindowVisualState)` . Not sure if there's a way to not take the focus when changing state though. With PInvoke / findWindow, you could easily determine the window that had focus before and give it the focus back right away but maybe there's a cleaner approach. – Sage Pourpre Jan 09 '22 at 10:14
  • Thanks for updating, @SagePourpre - and good point re `$wp.SetWindowVisualState($wp.Current.WindowVisualState)`. As for not activating: your original [`ShowWindowAsync`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindowasync) P/Invoke approach would definitely work if you use `SW_SHOWNOACTIVATE` (or `SW_SHOWMINNOACTIVE` or `SW_SHOWNA`), but I was curious about a pure UIAutomation solution and couldn't find any. – mklement0 Jan 09 '22 at 15:42