如果我正确理解了这一点,那么这段代码应该捕获活动窗口并保持焦点。 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: $_"
}
我也试过
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);
}
答案 0 :(得分:3)
我使用此脚本执行此操作。根据需要进行修改......
例如,默认变量$ProcessNameRegEx
和$WindowTitleRegEx
将移动新的记事本窗口(只需启动其中几个而不指定文件)。
您可以将不同的正则表达式传递给脚本。根据您的需求进行编辑。
显示-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
}
答案 1 :(得分:3)
我找到了它:
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)
}
答案 2 :(得分:2)
您是否考虑过使用窗口名称? 我发现这段代码可以很好地工作并且不会占用很多空间:
$wshell = New-Object -ComObject wscript.shell
$wshell.AppActivate('New Tab - Google Chrome')
此外,如果您只需要Alt-TAB回到最后运行的内容(即:您需要集中精力在触发某些操作后返回脚本窗口),请尝试以下操作:
$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys('%{TAB}')
答案 3 :(得分:0)
注意:
*此答案部分使用与现有答案相同的技术,但还引入了一种新技术,旨在针对性地对比这些方法,尤其是在PowerShell Core 。
*只有下面的 last 解决方案-需要通过Add-Member
按需编译C#代码-如果恰好是 minimized ,则会正确激活窗口。
*所有解决方案均使用PSv4 +语法;除非明确指出,否则它们都可以在Windows PowerShell和PowerShell Core(在Windows上)中使用。
基于 Add-Type
COM对象的WScript.Shell
,可以使用不需要.AppActivate()
且带有WinAPI P /调用签名的更简单的解决方案方法(Inventologist's answer提示):
注意:
如果在打开的窗口中窗口标题不是唯一的,则可能激活了错误的窗口;请参阅以下有关通过PID(进程ID)激活的解决方案
如果目标窗口恰好是 minimized ,则此解决方案会将 focus 置于其上,但不会还原 >。
function Show-Window {
param(
[Parameter(Mandatory)]
[string] $ProcessName
)
# As a courtesy, strip '.exe' from the name, if present.
$ProcessName = $ProcessName -replace '\.exe$'
# Get the title 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.
$winTitle = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, 'First').MainWindowTitle
if (-not $winTitle) { 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($winTitle)
}
# Sample invocation
Show-Window notepad
一种更可靠的方法是通过PID(进程ID)激活。
以下解决方案使用[Microsoft.VisualBasic.Interaction]
类型的静态.AppActivate()
方法,该方法也接受PID。
注意:
此解决方案仅适用于 Windows PowerShell ,不适用于PowerShell Core 。
如果目标窗口恰好是 minimized ,则此解决方案会将 focus 置于其上,但不会还原 >。
function Show-Window {
param(
[Parameter(Mandatory)]
[string] $ProcessName
)
if ($PSVersionTable.PSVersion.Major -le 5) { Throw "This function is only supported in PowerShell Core." }
# 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.
$targetPid = (Get-Process -ErrorAction Ignore $ProcessName).Where({ $_.MainWindowTitle }, 'First').Id
if (-not $targetPid) { Throw "No $ProcessName process with a non-empty window title found." }
# Load the required assembly.
Add-Type -ErrorAction Stop -AssemblyName Microsoft.VisualBasic
# 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*.
[Microsoft.VisualBasic.Interaction]::AppActivate($targetPid)
}
# Sample invocation
Show-Window notepad
还可以在PowerShell Core (在Windows上)中使用的 PID激活(进程ID)解决方案,确实需要 Add-Type
和WinAPI P / Invoke声明:
注意:
在PowerShell会话中首次调用该功能时,由于必须编译提供WinAPI访问权限的帮助程序类型,因此会出现明显的延迟。
与上述解决方案不同,此解决方案还原当前最小化的窗口以确保其内容可见,同时正确激活当前最大化的窗口而不恢复它。
< / li>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