How to set a foreground window from a Powershell event subscriber action

I have a FileSystemWatcher instance running in the background of my PoSh session that is viewing changes in text files. The PoSh event subscriber connects to this event, and at startup launches the console program by calling Start-Process . This program steals focus from the current foreground window (my PoSh console). Calling SetForegroundWindow from a PoSh event subscriber to return focus to my PoSh console does not work. SwitchToThisWindow works most of the time, but according to MSDN docs, it is not used.

Can I prevent the Start-Process from stealing focus in this situation or set it back from the event subscriber to the window that it had before this event?

+3
source share
3 answers

It SetForegroundWindowworks well for me . Check this code:

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@
sleep -sec 2
$h = (Get-Process firefox).MainWindowHandle
[void] [Tricks]::SetForegroundWindow($h)
sleep -sec 2
$h = (Get-Process -id $pid).MainWindowHandle
[void] [Tricks]::SetForegroundWindow($h)

But remember that if you host PowerShell or use, for example, the Console ( http://sourceforge.net/projects/console/ ), then MainWindowHandle is the handle to your host program. Therefore, (Get-Process -id $pid).MainWindowHandleyou will need instead [tricks]::SetForegroundWindow((Get-Process console).MainWindowHandle).

Example with a timer event:

$timer = New-Object Timers.Timer
$timer.Interval = 5000
$h = (Get-Process -id $pid).MainWindowHandle
$action = { 
    notepad; 
    sleep -sec 1;  # wait until the program starts (very simple approach)
    [Tricks]::SetForegroundWindow($h) }
Register-ObjectEvent $timer Elapsed -Action $action
$timer.Start()

Otherwise, if you run a process that hides its window, it may solve your problem.

$ps = new-object system.diagnostics.processstartinfo 'notepad'
$ps.windowStyle = 'hidden'
[system.diagnostics.process]::Start($ps)

, msdn Process class

+13

, , , .

? , .

- , 10

Start-Job -ScriptBlock {
    1..100 | %{
        sleep -Milliseconds 100
        #Set focus back
    }
}

GetForegroundWindow, , ,

http://www.leeholmes.com/blog/MorePInvokeInPowerShell.aspx

+1

@stej, , , , , , script , ISE, cmd ( ).

#bring script back into focus
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@

$parent = Get-Process -id ((gwmi win32_process -Filter "processid='$pid'").parentprocessid)
If ($parent.Name -eq "cmd") {# Being run by via cmd prompt (batch file)
    $h = (Get-Process cmd).MainWindowHandle
    [void] [Tricks]::SetForegroundWindow($h)
    }
    else{# being run in powershell ISE or console
          $h = (Get-Process -id $pid).MainWindowHandle
          [void] [Tricks]::SetForegroundWindow($h)
    } 

, .psm1 - PS v3 , , , ,

, Import-Module .\Getfocus.psm1 (, ).

Function Get-Focus{
#bring script back into focus
Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@

$parent = Get-Process -id ((gwmi win32_process -Filter "processid='$pid'").parentprocessid)
If ($parent.Name -eq "cmd") {# Being run by via cmd prompt (batch file)
    $h = (Get-Process cmd).MainWindowHandle
    [void] [Tricks]::SetForegroundWindow($h)
    }
    else{# being run in powershell ISE or console
          $h = (Get-Process -id $pid).MainWindowHandle
          [void] [Tricks]::SetForegroundWindow($h)
    }
} 

Export-ModuleMember -Function Get-Focus
0

Source: https://habr.com/ru/post/1739385/


All Articles