Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute a powershell script without stealing focus?

Tags:

powershell

I made a powershell script that uses GetForegroundWindow() to identify which Window is the currently focused Window. Unfortunately, when the powershell script is executed (via Windows Task Scheduler or a hotkey), the script steals focus of the current foreground app; incorrectly using the Powershell window itself as the Foreground app, instead of the intended foreground app.

I even tried creating an EXE using PS2EXE "-noconsole" setting; however, the script still doesn't doesn't work.

Could someone please suggest a way to execute this script without changing focus of the current foreground Window?

My script code works during tests (ONLY if I add "Start-Sleep -s 5"; and, manually steal back the focus with alt-tab for the script to identify the correct foreground Window.

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}
"@


function Set-WindowStyle {
param(
    [Parameter()]
    [ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE',
                 'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED',
                 'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')]
    $Style = 'SHOW',
    [Parameter()]
    $MainWindowHandle = (Get-Process -Id $pid).MainWindowHandle
)
    $WindowStates = @{
        FORCEMINIMIZE   = 11; HIDE            = 0
        MAXIMIZE        = 3;  MINIMIZE        = 6
        RESTORE         = 9;  SHOW            = 5
        SHOWDEFAULT     = 10; SHOWMAXIMIZED   = 3
        SHOWMINIMIZED   = 2;  SHOWMINNOACTIVE = 7
        SHOWNA          = 8;  SHOWNOACTIVATE  = 4
        SHOWNORMAL      = 1
    }
    Write-Verbose ("Set Window Style {1} on handle {0}" -f $MainWindowHandle, $($WindowStates[$style]))

    $Win32ShowWindowAsync = Add-Type -memberDefinition @"
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@ -name "Win32ShowWindowAsync" -namespace Win32Functions -passThru

    $Win32ShowWindowAsync::ShowWindowAsync($MainWindowHandle, $WindowStates[$Style]) | Out-Null
}


$a = [tricks]::GetForegroundWindow()

$title = get-process | ? { $_.mainwindowhandle -eq $a }
$title2 = $title | select -ExpandProperty ProcessName

if ($title2 -eq 'Kodi'){

    Set-WindowStyle MINIMIZE $a;
    if (Get-Process -Name Yatse2) {(Get-Process -Name Yatse2).MainWindowHandle | foreach { Set-WindowStyle MINIMIZE $_ }}

} ELSE {

    $title.CloseMainWindow()
}
like image 833
MKANET Avatar asked Apr 07 '15 16:04

MKANET


People also ask

How do I run a PowerShell script without confirmation?

When you want to do a big script in PowerShell, sometimes it keeps asking you for confirmation even if you did not put the “-Confirm” parameter in your command. The answer is simple, just add -Confirm:$false .

How do I run a PowerShell script directly?

In File Explorer (or Windows Explorer), right-click the script file name and then select "Run with PowerShell". The "Run with PowerShell" feature starts a PowerShell session that has an execution policy of Bypass, runs the script, and closes the session.

How do I run a PowerShell script without displaying Windows?

To totally remove window you can do one of two things: 1: Run in a different user's context such as admin account (won't display any windows to the logged on user). Or 2: Use a vbscript with objshell. run with a hidden window flag to launch cmd.exe /c powershel.exe -file c:\script.


1 Answers

I know this question is old, but I've spent quite some time trying to figure out how to not lose focus from the current window for myself and found some information, so hopefully this will help future readers.

The easiest solution is just to literally simulate an Alt+Tab keypress from within your Powershell script instead of having to do it yourself. The following code comes from this StackOverflow answer:

[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
[System.Windows.Forms.SendKeys]::SendWait("%{TAB}")
# Retrieve the window handles...

...where % represents the Alt modifier and {TAB} is interpreted as the tab key.

like image 174
homersimpson Avatar answered Oct 10 '22 09:10

homersimpson