如何通过进程名称将焦点移到窗口?

use*_*022 5 powershell

如果我正确理解了此代码,则该代码应捕获活动窗口并保持其焦点。concentr.exe是进程名称。如何根据进程名称使窗口聚焦?

Add-Type @"
using System;
using System.Runtime.InteropServices;
public class UserWindows {
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
}
"@            
try {            
$ActiveHandle = [UserWindows]::GetForegroundWindow()
$Process = Get-Process | ? {$_.MainWindowHandle -eq $activeHandle}            
$Process | Select ProcessName, @{Name="concentr.exe";Expression=    {($_.MainWindowTitle)}}            
 } catch {            
 Write-Error "Failed to get active Window details. More Info: $_"            
 }
Run Code Online (Sandbox Code Playgroud)

我也尝试过

param([string] $proc="Citrix Connection Manager", [string]$adm)
cls

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" #-Verb runAs
 }
 else
 {
  $h = $p.MainWindowHandle

[void] [WinAp]::SetForegroundWindow($h)
[void] [WinAp]::ShowWindow($h,3);
 }
Run Code Online (Sandbox Code Playgroud)

mkl*_*nt0 14

注意:
\n\xe2\x80\xa2 这个答案部分使用了与现有答案相同的技术,但也引入了一种新技术,旨在集中对比这些方法。
\n\xe2\x80\xa2 只有下面的最后一个解决方案 - 需要通过按需编译 C# 代码Add-Member- 如果窗口恰好被最小化,则可以正确激活窗口。
\n\xe2\x80\xa2 所有解决方案均使用 PSv4+ 语法。

\n
\n

重要的

\n
    \n
  • 除非您的代码在当前前台窗口中运行,否则Windows默认情况下会阻止以编程方式激活其他进程的窗口:其任务栏图标会闪烁,而不是激活目标窗口

    \n
  • \n
  • 启用无条件编程激活需要额外的工作,通过每个会话 P/Invoke 调用 - 请参阅此答案

    \n
  • \n
\n
\n

基于COM 对象的方法发明家的回答) ,可以有一个不需要Add-TypeWinAPI P/Invoke 签名的更简单的解决方案WScript.Shell.AppActivate()暗示)

\n

笔记

\n
    \n
  • 如果目标窗口恰好被最小化,此解决方案确实会将焦点放在它上面,但不会恢复它。

    \n
  • \n
  • 解决方案的要点如下,Notepad以进程名称为例;该语句激活具有非空窗口标题的该名称的(第一个)进程(如果您可以假设目标进程始终具有窗口标题,因此可以假定为可见,您可以简化为(Get-Process Notepad)[0].Id):

    \n
    $null = (New-Object -ComObject WScript.Shell).AppActivate(\n  (Get-Process Notepad).Where({ $_.MainWindowTitle }, \'First\').Id\n)\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
\n
function Show-Window {\n  param(\n    [Parameter(Mandatory)]\n    [string] $ProcessName\n  )\n\n  # As a courtesy, strip \'.exe\' from the name, if present.\n  $ProcessName = $ProcessName -replace \'\\.exe$\'\n\n  # Get the ID of the first instance of a process with the given name\n  # that has a non-empty window title.\n  # NOTE: If multiple instances have visible windows, it is undefined\n  #       which one is returned.\n  $procId = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, \'First\').Id\n\n  if (-not $procId) { Throw "No $ProcessName process with a non-empty window title found." }\n\n  # Note: \n  #  * This can still fail, because the window could have been closed since\n  #    the title was obtained.\n  #  * If the target window is currently minimized, it gets the *focus*, but is\n  #    *not restored*.\n  #  * The return value is $true only if the window still existed and was *not\n  #    minimized*; this means that returning $false can mean EITHER that the\n  #    window doesn\'t exist OR that it just happened to be minimized.\n  $null = (New-Object -ComObject WScript.Shell).AppActivate($procId)\n\n}\n\n# Sample invocation\nShow-Window notepad\n
Run Code Online (Sandbox Code Playgroud)\n
\n

如果目标窗口恰好最小化,也可以恢复目标窗口的解决方案需要Add-Type使用 WinAPI P/Invoke 声明

\n

笔记

\n
    \n
  • 在 PowerShell 会话中首次调用该函数时,由于必须编译提供 WinAPI 访问的帮助程序类型,因此存在明显的延迟。

    \n
  • \n
  • 与上面的解决方案不同,该解决方案恢复当前最小化的窗口以确保其内容可见,同时正确激活当前最大化的窗口而不恢复它。

    \n
  • \n
\n
function Show-Window {\n  param(\n    [Parameter(Mandatory)]\n    [string] $ProcessName\n  )\n\n  # As a courtesy, strip \'.exe\' from the name, if present.\n  $ProcessName = $ProcessName -replace \'\\.exe$\'\n\n  # Get the PID of the first instance of a process with the given name\n  # that has a non-empty window title.\n  # NOTE: If multiple instances have visible windows, it is undefined\n  #       which one is returned.\n  $hWnd = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, \'First\').MainWindowHandle\n\n  if (-not $hWnd) { Throw "No $ProcessName process with a non-empty window title found." }\n\n  $type = Add-Type -PassThru -NameSpace Util -Name SetFgWin -MemberDefinition @\'\n    [DllImport("user32.dll", SetLastError=true)]\n    public static extern bool SetForegroundWindow(IntPtr hWnd);\n    [DllImport("user32.dll", SetLastError=true)]\n    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);    \n    [DllImport("user32.dll", SetLastError=true)]\n    public static extern bool IsIconic(IntPtr hWnd);    // Is the window minimized?\n\'@ \n\n  # Note: \n  #  * This can still fail, because the window could have been closed since\n  #    the title was obtained.\n  #  * If the target window is currently minimized, it gets the *focus*, but its\n  #    *not restored*.\n  $null = $type::SetForegroundWindow($hWnd)\n  # If the window is minimized, restore it.\n  # Note: We don\'t call ShowWindow() *unconditionally*, because doing so would\n  #       restore a currently *maximized* window instead of activating it in its current state.\n  if ($type::IsIconic($hwnd)) {\n    $type::ShowWindow($hwnd, 9) # SW_RESTORE\n  }\n\n}\n\n# Sample invocation\nShow-Window notepad\n
Run Code Online (Sandbox Code Playgroud)\n


use*_*022 9

我找到了:

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)
}
Run Code Online (Sandbox Code Playgroud)


Inv*_*ist 7

你有没有想过使用窗口名称?我发现这段代码很好用,而且不占用太多空间:

$wshell = New-Object -ComObject wscript.shell
$wshell.AppActivate('New Tab - Google Chrome')
Run Code Online (Sandbox Code Playgroud)

此外,如果您只需要按 Alt-TAB 键返回上次运行的内容(即:您需要在关闭某些内容后将焦点返回到脚本窗口),请尝试以下操作:

$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys('%{TAB}')
Run Code Online (Sandbox Code Playgroud)


Kor*_*ill 3

我使用这个脚本来做到这一点。根据需要修改...

例如,默认变量$ProcessNameRegEx$WindowTitleRegEx将移动新的记事本窗口(只需启动其中几个而不指定文件)。

您可以将不同的正则表达式传递给脚本。根据您的需求进行编辑。

按名称显示窗口

#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
}
Run Code Online (Sandbox Code Playgroud)