If I\'m understanding this correctly this code should capture the active window and keep it in focus. concentr.exe is the process name. How do I bring a window in focus base
I found it:
Param(
[string] $proc="C:\Program Files (x86)\Citrix\ICA Client\concentr.exe",
[string] $adm
)
Clear-Host
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class WinAp {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
"@
$p = Get-Process | Where {$_.mainWindowTitle} |
Where {$_.Name -like "$proc"}
if (($p -eq $null) -and ($adm -ne "")) {
Start-Process "$proc" -Verb runAs
} elseif (($p -eq $null) -and ($adm -eq "")) {
Start-Process "$proc"
} else {
$h = $p.MainWindowHandle
[void] [WinAp]::SetForegroundWindow($h)
[void] [WinAp]::ShowWindow($h, 3)
}
Have you thought of using the Window Name? I've found this bit of code to work great and not take up a lot of space:
$wshell = New-Object -ComObject wscript.shell
$wshell.AppActivate('New Tab - Google Chrome')
Also, if you need to just Alt-TAB back to the last thing that ran (ie: you need focus to come back to the script window after firing something off) try this:
$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys('%{TAB}')
I use this script to do this. Modify as you need...
For example, the default variables $ProcessNameRegEx
and $WindowTitleRegEx
will move new Notepad windows (just start a couple of them with no file specifed).
You can pass different regex expressions to the script. Edit as makes sense to your needs.
Show-WindowByName
#Requires -RunAsAdministrator
[CmdletBinding()]
param (
[string]
$ProcessNameRegEx = 'notepad',
[string]
$WindowTitleRegEx = 'unt'
)
$cs = @"
using System;
using System.Runtime.InteropServices;
namespace User32
{
public static class WindowManagement
{
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
public const int SWP_NOSIZE = 0x01, SWP_NOMOVE = 0x02, SWP_SHOWWINDOW = 0x40, SWP_HIDEWINDOW = 0x80;
public static void SetWindowPosWrappoer(IntPtr handle, int x, int y, int width, int height)
{
if (handle != null)
{
SetWindowPos(handle, 0, x, y, 0, 0, SWP_NOSIZE | SWP_HIDEWINDOW);
if (width > -1 && height > -1)
SetWindowPos(handle, 0, 0, 0, width, height, SWP_NOMOVE);
SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
}
}
[DllImport("user32.dll", EntryPoint = "ShowWindow")]
public static extern IntPtr ShowWindow(IntPtr hWnd, int nCmdShow);
public static void ShowWindowWrapper(IntPtr handle, int nCmdShow)
{
if (handle != null)
{
ShowWindow(handle, nCmdShow);
}
}
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
public static extern IntPtr SetForegroundWindow(IntPtr hWnd);
public static void SetForegroundWindowWrapper(IntPtr handle)
{
if (handle != null)
{
SetForegroundWindow(handle);
}
}
}
}
"@
Add-Type -TypeDefinition $cs -Language CSharp -ErrorAction SilentlyContinue
function Move-Window
{
param (
[int]$MainWindowHandle,
[int]$PosX,
[int]$PosY,
[int]$Height,
[int]$Width
)
if($MainWindowHandle -ne [System.IntPtr]::Zero)
{
[User32.WindowManagement]::SetWindowPosWrappoer($MainWindowHandle, $PosX, $PosY, $Width, $Height);
}
else
{
throw "Couldn't find the MainWindowHandle, aborting (your process should be still alive)"
}
}
function Show-Window
{
param (
[int]$MainWindowHandle,
[int]$CmdShow
)
if($MainWindowHandle -ne [System.IntPtr]::Zero)
{
[User32.WindowManagement]::ShowWindowWrapper($MainWindowHandle, $CmdShow);
[User32.WindowManagement]::SetForegroundWindowWrapper($MainWindowHandle);
}
else
{
throw "Couldn't find the MainWindowHandle, aborting (your process should be still alive)"
}
}
$windows = Get-Process | ? {$_.ProcessName -match $ProcessNameRegEx -and $_.MainWindowTitle -match $WindowTitleRegEx} | Select -Last 100 | Select Id, MainWindowTitle, MainWindowHandle | Sort MainWindowTitle
$h = 180
$w = 1500
$x = 400
$y = 800
$deltax = 80
$deltay = 180
foreach ($window in $windows)
{
Move-Window $window.MainWindowHandle $x $y $h $w
Show-Window $window.MainWindowHandle 5
#$x -= $deltax
$y -= $deltay
}
Note:
* This answer in part uses the same technique as the existing answers, but also introduces a new technique, and aims to contrast the approaches in a focused manner, particularly with respect to whether they're also supported in PowerShell Core.
* Only the last solution below - which requires on-demand compilation of C# code via Add-Member
- properly activates a window if it happens to be minimized.
* All solutions use PSv4+ syntax; unless explicitly noted, they work in both Windows PowerShell and PowerShell Core (on Windows).
A simpler solution that doesn't require Add-Type
with WinAPI P/Invoke signatures is possible, based on the WScript.Shell
COM object's .AppActivate()
method (which Inventologist's answer hints at):
Note:
function Show-Window {
param(
[Parameter(Mandatory)]
[string] $ProcessName
)
# As a courtesy, strip '.exe' from the name, if present.
$ProcessName = $ProcessName -replace '\.exe$'
# Get the ID of the first instance of a process with the given name
# that has a non-empty window title.
# NOTE: If multiple instances have visible windows, it is undefined
# which one is returned.
$procId = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, 'First').Id
if (-not $procId) { Throw "No $ProcessName process with a non-empty window title found." }
# Note:
# * This can still fail, because the window could have been closed since
# the title was obtained.
# * If the target window is currently minimized, it gets the *focus*, but is
# *not restored*.
# * The return value is $true only if the window still existed and was *not
# minimized*; this means that returning $false can mean EITHER that the
# window doesn't exist OR that it just happened to be minimized.
$null = (New-Object -ComObject WScript.Shell).AppActivate($procId)
}
# Sample invocation
Show-Window notepad
A solution that also restores the target window if it happens to be minimized requires Add-Type
with WinAPI P/Invoke declarations:
Note:
On first invocation of the function in a PowerShell session, there is a noticeable delay due to having to compile the helper type that provides WinAPI access.
Unlike the solution above, this solution restores a currently minimized window to ensure that its content is visible, while properly activating a currently-maximized window without restoring it.
function Show-Window {
param(
[Parameter(Mandatory)]
[string] $ProcessName
)
# As a courtesy, strip '.exe' from the name, if present.
$ProcessName = $ProcessName -replace '\.exe$'
# Get the PID of the first instance of a process with the given name
# that has a non-empty window title.
# NOTE: If multiple instances have visible windows, it is undefined
# which one is returned.
$hWnd = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, 'First').MainWindowHandle
if (-not $hWnd) { Throw "No $ProcessName process with a non-empty window title found." }
$type = Add-Type -PassThru -NameSpace Util -Name SetFgWin -MemberDefinition @'
[DllImport("user32.dll", SetLastError=true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError=true)]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError=true)]
public static extern bool IsIconic(IntPtr hWnd); // Is the window minimized?
'@
# Note:
# * This can still fail, because the window could have bee closed since
# the title was obtained.
# * If the target window is currently minimized, it gets the *focus*, but its
# *not restored*.
$null = $type::SetForegroundWindow($hWnd)
# If the window is minimized, restore it.
# Note: We don't call ShowWindow() *unconditionally*, because doing so would
# restore a currently *maximized* window instead of activating it in its current state.
if ($type::IsIconic($hwnd)) {
$type::ShowWindow($hwnd, 9) # SW_RESTORE
}
}
# Sample invocation
Show-Window notepad