Add-Type -AssemblyName System.Windows.Forms
# 新規ウィンドウ検索比較用
$global:currentWindowList = @()
# Win32 API
Add-Type @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public class Win32 {
/******************************/
// 構造体
/******************************/
public struct POINT {
public int X;
public int Y;
}
public struct RECT {
public int Left;
public int Top;
public int Right;
public int Bottom;
}
/******************************/
// ウィンドウ
/******************************/
[DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int GetWindowTextW(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")] public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
[DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")] public static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr hWnd);
[DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow();
/******************************/
// キーボード
/******************************/
[DllImport("user32.dll")] public static extern short GetAsyncKeyState(int vKey);
[DllImport("user32.dll")] public static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
[DllImport("user32.dll")] public static extern IntPtr GetKeyboardLayout(uint idThread);
[DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
/******************************/
// マウス
/******************************/
[DllImport("user32.dll")] public static extern IntPtr WindowFromPoint(POINT p);
[DllImport("user32.dll")] public static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")] public static extern bool GetCursorPos(out POINT p);
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")] public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
/******************************/
//
/******************************/
[DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
}
"@
#ShowWindow 定数定義
$SW_HIDE = 0 #ウィンドウを非表示にする
$SW_SHOWNORMAL = 1 #通常のサイズと位置で表示(最小化や最大化を解除)
$SW_SHOWMINIMIZED = 2 #ウィンドウを最小化して表示
$SW_SHOWMAXIMIZED = 3 #ウィンドウを最大化して表示
$SW_SHOWNOACTIVATE = 4 #ウィンドウを現在の位置で表示するが、アクティブにしない
$SW_SHOW = 5 #ウィンドウを表示(現在のサイズと位置)
$SW_MINIMIZE = 6 #ウィンドウを最小化
$SW_SHOWMINNOACTIVE = 7 #最小化して表示するが、アクティブにしない
$SW_SHOWNA = 8 #ウィンドウを表示するが、アクティブにしない
$SW_RESTORE = 9 #最小化または最大化されたウィンドウを通常状態に戻す
$SW_SHOWDEFAULT = 10 #STARTUPINFO 構造体に指定されたデフォルトの表示状態で表示
$SW_FORCEMINIMIZE = 11 #強制的に最小化(リモートセッションで有効)
# mouse_event フラグ定数定義(Win32API)
$MOUSEEVENTF_MOVE = 0x0001 # マウスカーソルを移動
$MOUSEEVENTF_LEFTDOWN = 0x0002 # 左ボタンを押す
$MOUSEEVENTF_LEFTUP = 0x0004 # 左ボタンを離す
$MOUSEEVENTF_RIGHTDOWN = 0x0008 # 右ボタンを押す
$MOUSEEVENTF_RIGHTUP = 0x0010 # 右ボタンを離す
$MOUSEEVENTF_MIDDLEDOWN = 0x0020 # 中央ボタン(ホイール)を押す
$MOUSEEVENTF_MIDDLEUP = 0x0040 # 中央ボタンを離す
$MOUSEEVENTF_XDOWN = 0x0080 # 拡張ボタン(XBUTTON1 または XBUTTON2)を押す
$MOUSEEVENTF_XUP = 0x0100 # 拡張ボタンを離す
$MOUSEEVENTF_WHEEL = 0x0800 # 垂直スクロールホイールを回す(dwData に量を指定)
$MOUSEEVENTF_HWHEEL = 0x01000 # 水平スクロールホイールを回す(dwData に量を指定)
$MOUSEEVENTF_ABSOLUTE = 0x8000 # 絶対座標指定(画面全体を 65535x65535 として扱う)
# SendMassage フラグ定数定義(Win32API)
$WM_MOUSEMOVE = 0x0200
$WM_LBUTTONDOWN = 0x0201
$WM_LBUTTONUP = 0x0202
$WM_LBUTTONDBLCLK = 0x0203
$MK_LBUTTON = 0x0001
# keybd_event定数定義
$KEYEVENTF_KEYDOWN = 0x0000
$KEYEVENTF_KEYUP = 0x0002
# 仮想キーコード定義
$VK_BACK = 0x08 # Backspace
$VK_TAB = 0x09 # Tab
$VK_RETURN = 0x0D # Enter
$VK_SHIFT = 0x10 # Shift
$VK_CONTROL = 0x11 # Ctrl
$VK_MENU = 0x12 # Alt
$VK_PAUSE = 0x13 # Pause
$VK_CAPITAL = 0x14 # Caps Lock
$VK_ESCAPE = 0x1B # Esc
$VK_SPACE = 0x20 # Space
$VK_PRIOR = 0x21 # Page Up
$VK_NEXT = 0x22 # Page Down
$VK_END = 0x23 # End
$VK_HOME = 0x24 # Home
$VK_LEFT = 0x25 # ←
$VK_UP = 0x26 # ↑
$VK_RIGHT = 0x27 # →
$VK_DOWN = 0x28 # ↓
$VK_SCROLL = 0x91 # Scroll Lock
$VK_INSERT = 0x2D # Insert
$VK_DELETE = 0x2E # Delete
$VK_LWIN = 0x5B # Windowsキー(左)
$VK_KANA = 0xF3 # 半角/全角(IME切替)
# ファンクションキー
$VK_F1 = 0x70
$VK_F2 = 0x71
$VK_F3 = 0x72
$VK_F4 = 0x73
$VK_F5 = 0x74
$VK_F6 = 0x75
$VK_F7 = 0x76
$VK_F8 = 0x77
$VK_F9 = 0x78
$VK_F10 = 0x79
$VK_F11 = 0x7A
$VK_F12 = 0x7B
# 数字キー(上段)
$VK_0 = 0x30
$VK_1 = 0x31
$VK_2 = 0x32
$VK_3 = 0x33
$VK_4 = 0x34
$VK_5 = 0x35
$VK_6 = 0x36
$VK_7 = 0x37
$VK_8 = 0x38
$VK_9 = 0x39
$VK_MINUS = 0xBD # ハイフン(-)キー
# アルファベットキー
$VK_A = 0x41 # A
$VK_B = 0x42 # B
$VK_C = 0x43 # C
$VK_D = 0x44 # D
$VK_E = 0x45 # E
$VK_F = 0x46 # F
$VK_G = 0x47 # G
$VK_H = 0x48 # H
$VK_I = 0x49 # I
$VK_J = 0x4A # J
$VK_K = 0x4B # K
$VK_L = 0x4C # L
$VK_M = 0x4D # M
$VK_N = 0x4E # N
$VK_O = 0x4F # O
$VK_P = 0x50 # P
$VK_Q = 0x51 # Q
$VK_R = 0x52 # R
$VK_S = 0x53 # S
$VK_T = 0x54 # T
$VK_U = 0x55 # U
$VK_V = 0x56 # V
$VK_W = 0x57 # W
$VK_X = 0x58 # X
$VK_Y = 0x59 # Y
$VK_Z = 0x5A # Z
# テンキー
$VK_NUMPAD0 = 0x60 # 0
$VK_NUMPAD1 = 0x61 # 1
$VK_NUMPAD2 = 0x62 # 2
$VK_NUMPAD3 = 0x63 # 3
$VK_NUMPAD4 = 0x64 # 4
$VK_NUMPAD5 = 0x65 # 5
$VK_NUMPAD6 = 0x66 # 6
$VK_NUMPAD7 = 0x67 # 7
$VK_NUMPAD8 = 0x68 # 8
$VK_NUMPAD9 = 0x69 # 9
$VK_MULTIPLY = 0x6A # *
$VK_ADD = 0x6B # +
$VK_SEPARATOR = 0x6C # 区切り(通常未使用)
$VK_SUBTRACT = 0x6D # -
$VK_DECIMAL = 0x6E # .
$VK_DIVIDE = 0x6F # /
# 差分マップ(VK名と文字列が一致しないものだけ)
$specialMap = @{
"ENTER" = "VK_RETURN"
"ESC" = "VK_ESCAPE"
"PGUP" = "VK_PRIOR"
"PGDN" = "VK_NEXT"
"DEL" = "VK_DELETE"
"INS" = "VK_INSERT"
}
$ModifierKeys = @{
Ctrl = $false
Shift = $false
Alt = $false
}
$modMap = @{
'^' = 'Ctrl'
'+' = 'Shift'
'%' = 'Alt'
}
# 拡張キー
$VK_RCONTROL = 0xA3 # RightCtrl
$VK_NUMPADRETURN = 0x0D # テンキー Enter(※ExtendedKeyフラグ付きで区別)
$VK_NUMLOCK = 0x90 # NumLock
$SCAN_RCONTROL = 0x1D # RightCtrl
$SCAN_NUMPADRETURN = 0x1C # テンキー Enter
$SCAN_NUMLOCK = 0x45 # NumLock
$KEYEVENTF_EXTENDEDKEY = 0x0001
# 拡張キーとして扱う仮想キーコード一覧
$ExtendedKeySet = @(
$VK_NUMLOCK,
$VK_SCROLL,
$VK_INSERT,
$VK_DELETE,
$VK_HOME,
$VK_END,
$VK_PRIOR, # Page Up
$VK_NEXT, # Page Down
$VK_LEFT,
$VK_RIGHT,
$VK_UP,
$VK_DOWN,
$VK_RCONTROL,
$VK_NUMPADRETURN
)
# 空のハッシュテーブルを用意
$vktable = @{}
# グローバルに定義されている $VK_* 変数を拾って、名前→値 で格納
Get-Variable -Name 'VK_*' -Scope Global | ForEach-Object {
# Name は "$" を含まないのでそのままキーに使えます
$vktable[$_.Name] = $_.Value
}
# 関数:拡張キー自動判別
function Is-ExtendedKey([byte]$vk) {
return $ExtendedKeySet -contains $vk
}
# 関数:仮想キーコード取得
function ConvertTo-VK {
param([char]$ch)
$hkl = [Win32]::GetKeyboardLayout(0)
$code = [Win32]::VkKeyScanEx($ch, $hkl)
if ($code -eq -1) { return $null }
$vk = $code -band 0xFF
$shift = ($code -band 0x0100) -ne 0
return @{ VK = $vk; Shift = $shift; Repeat = 1 }
}
# 関数:メッセージボックス前面表示用フォーム使用版
function MsgBox {
param(
[string]$Message = "お知らせ",
[string]$title = "通知",
[string]$button = "OK",
[string]$icon = "Information"
)
Add-Type -AssemblyName System.Windows.Forms
$buttonInput = $button.ToLower()
$button = [System.Enum]::GetNames([System.Windows.Forms.MessageBoxButtons]) |
Where-Object { $_.ToLower() -eq $buttonInput }
if ($null -eq $button -or ($button).Count -ne 1) {
$button = "OK"
}
$iconInput = $icon.ToLower()
$icon = [System.Enum]::GetNames([System.Windows.Forms.MessageBoxIcon]) |
Where-Object { $_.ToLower() -eq $iconInput }
if ($null -eq $icon -or ($icon).Count -ne 1) {
$icon = "Information"
}
$button = [System.Windows.Forms.MessageBoxButtons]::$button
$icon = [System.Windows.Forms.MessageBoxIcon]::$icon
# --- owner フォーム ---
$owner = New-Object System.Windows.Forms.Form
$owner.Text = "メッセージボックス用"
$owner.StartPosition = 'Manual'
$owner.Size = '1,1'
$owner.Location = '-32000,-32000'
$owner.ShowInTaskbar = $true
$owner.TopMost = $true
$owner.Show()
[void][System.Windows.Forms.Application]::DoEvents()
$owner.BringToFront()
$owner.Activate()
$result = [System.Windows.Forms.MessageBox]::Show($owner, $Message, $title, $button, $icon)
$owner.Close()
$owner.Dispose()
return $result
}
# 強制終了キーセット
$global:InterruptKeys = @{
STOPKEY1 = $VK_CONTROL
STOPKEY2 = $VK_MENU
STOPKEY3 = $VK_P
}
# 関数:強制終了キー押下チェック(押しっぱなし)
function Check-Interrupt {
$pressedStates = @()
foreach ($key in $global:InterruptKeys.Keys) {
$vk = $global:InterruptKeys[$key]
$isDown = ([Win32]::GetAsyncKeyState($vk) -band 0x8000) -ne 0
$pressedStates += $isDown
}
# すべてのキーが押されていれば割り込み
if ($pressedStates -notcontains $false) {
$global:StopFlag = $true
}
}
# 関数:強制終了実行(呼び出し元でtry/catch)
function Invoke-Step {
param([ScriptBlock]$Action = $null)
Check-Interrupt
if ($global:StopFlag) {
MsgBox "処理を中断しました" "強制終了" "OK" "Error"
exit
#throw "割り込み検出:処理中断"
}
if ($Action) {
& $Action
}
}
# 関数:キーを押す
function Send-KeyDown([byte]$vk, [byte]$scan = 0, [bool]$isExtended = $false) {
Invoke-Step
$flags = $KEYEVENTF_KEYDOWN
if ($isExtended -or (Is-ExtendedKey $vk)) {
$flags = $flags -bor $KEYEVENTF_EXTENDEDKEY
}
[Win32]::keybd_event($vk, $scan, $flags, 0)
}
# 関数:キーを離す
function Send-KeyUp([byte]$vk, [byte]$scan = 0, [bool]$isExtended = $false) {
Invoke-Step
$flags = $KEYEVENTF_KEYUP
if ($isExtended -or (Is-ExtendedKey $vk)) {
$flags = $flags -bor $KEYEVENTF_EXTENDEDKEY
}
[Win32]::keybd_event($vk, $scan, $flags, 0)
}
# 関数:キーを押して離す
function Send-KeyPress([byte]$vk, [byte]$scan = 0, [bool]$isExtended = $false, [int]$repeat = 1) {
for($i = 0; $i -lt $repeat; $i++){
Invoke-Step
Send-KeyDown -vk $vk -scan $scan -isExtended $isExtended
Start-Sleep -Milliseconds 50
Send-KeyUp -vk $vk -scan $scan -isExtended $isExtended
}
}
# 関数:文字列(日本語不可)からSend-KeyPressを連続して実行
function Send-Keys {
param([string]$text)
Invoke-Step
$modStack = New-Object System.Collections.Generic.Stack[hashtable]
$currentMods = @{ Ctrl = $false; Shift = $false; Alt = $false }
# 物理キーの初期化
Send-KeyUp $VK_CONTROL
Send-KeyUp $VK_SHIFT
Send-KeyUp $VK_MENU
try {
for ($i = 0; $i -lt $text.Length; $i++) {
$ch = [char]$text[$i]
$info = $null
# 1. 修飾キー予約
if ($ch -eq '^') { $currentMods.Ctrl = $true; continue }
if ($ch -eq '+') { $currentMods.Shift = $true; continue }
if ($ch -eq '%') { $currentMods.Alt = $true; continue }
# 2. グループ化開始
if ($ch -eq '(') {
# 現在の状態を新しいハッシュテーブルとしてスタックに保存
$modStack.Push(@{
Ctrl = $currentMods.Ctrl
Shift = $currentMods.Shift
Alt = $currentMods.Alt
})
continue
}
# 3. グループ化終了
if ($ch -eq ')') {
if ($modStack.Count -gt 0) {
$currentMods = $modStack.Pop()
}
continue
}
# 4. 特殊キー解析 {}
if ($ch -eq '{') {
$end = $text.IndexOf('}', $i)
if ($end -gt $i) {
$token = $text.Substring($i + 1, $end - $i - 1)
$space = $token.IndexOf(' ')
if ($space -gt 0) {
$keyName = $token.Substring(0, $space).ToUpperInvariant()
$repeat = [int]$token.Substring($space + 1)
} else {
$keyName = $token.ToUpperInvariant()
$repeat = 1
}
$varName = $specialMap[$keyName]
if (-not $varName) { $varName = "VK_$keyName" }
$vk = $vktable[$varName]
if ($vk) {
$info = @{ VK = [byte]$vk; Shift = $false; Repeat = [int]$repeat }
} else {
if ($keyName.Length -eq 1) {
$info = ConvertTo-VK $keyName
$info.Repeat = [int]$repeat
}
}
$i = $end
}
}
# 5. 通常文字
else {
#$info = ConvertTo-VK $ch
$keyName = $ch.ToString().ToUpperInvariant()
$varName = "VK_$keyName"
$vk = $vktable[$varName]
$shift = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -cmatch $ch
if ($vk) {
$info = @{ VK = [byte]$vk; Shift = $shift; Repeat = 1 }
} else {
$info = ConvertTo-VK $ch
#$info.Repeat = 1
}
}
# --- 実行 ---
if ($null -ne $info) {
if ($currentMods.Ctrl) { Send-KeyDown $VK_CONTROL }
if ($currentMods.Shift -or $info.Shift) { Send-KeyDown $VK_SHIFT }
if ($currentMods.Alt) { Send-KeyDown $VK_MENU }
Start-Sleep -Milliseconds 50
Send-KeyPress -vk $info.VK -repeat $info.Repeat
if ($currentMods.Alt) { Send-KeyUp $VK_MENU }
if ($currentMods.Shift -or $info.Shift) { Send-KeyUp $VK_SHIFT }
if ($currentMods.Ctrl) { Send-KeyUp $VK_CONTROL }
# 括弧の外なら予約クリア
if ($modStack.Count -eq 0) {
$currentMods.Ctrl = $false
$currentMods.Shift = $false
$currentMods.Alt = $false
}
}
}
} catch {
Write-Error "Send-Keys内でエラーが発生しました: $_"
} finally {
# 最終安全装置
Send-KeyUp $VK_CONTROL
Send-KeyUp $VK_SHIFT
Send-KeyUp $VK_MENU
}
}
# 関数:NUMLOCK状態を返す
function Get-NumLockState {
return [console]::NumberLock
}
# 関数:NUMLOCK状態を指定の状態にする
function Set-NumLockState($desiredState) {
Invoke-Step
$currentState = Get-NumLockState
if ($currentState -ne $desiredState) {
# NumLock トグル
Send-KeyPress -vk $VK_NUMLOCK -scan $SCAN_NUMLOCK -isExtended $true
Start-Sleep -Milliseconds 100
}
}
########
# ウィンドウへクリック操作イベント用
function Make-LParam {
param(
[int]$low,
[int]$high
)
Invoke-Step
return (($low -band 0xFFFF) -bor (($high -band 0xFFFF) -shl 16))
}
function Invoke-WindowClick($TargethWnd, $x = 0, $y = 0, $DBLCLK = $false) {
Invoke-Step
if ($TargethWnd) {
$hWnd = $TargethWnd
# ウィンドウ矩形(スクリーン座標)
$rect = New-Object Win32+RECT
[void][Win32]::GetWindowRect($hWnd, [ref]$rect)
# クリックしたいスクリーン座標
$ptScreen = New-Object Win32+POINT
$ptScreen.X = $rect.Left + $x
$ptScreen.Y = $rect.Top + $y
# スクリーン座標 → クライアント座標に変換(対象はメインウィンドウのクライアント)
$ptClient = $ptScreen
[void][Win32]::ScreenToClient($hWnd, [ref]$ptClient)
# 必要なら事前に WM_MOUSEMOVE を投げて位置を更新
$lParamMove = Make-LParam $ptClient.X $ptClient.Y
[void][Win32]::SendMessage($hWnd, $WM_MOUSEMOVE, [IntPtr]0, $lParamMove)
# 左クリック(押下→解放)
$lParamClick = Make-LParam $ptClient.X $ptClient.Y
[void][Win32]::SendMessage($hWnd, $WM_LBUTTONDOWN, [IntPtr]$MK_LBUTTON, $lParamClick)
[void][Win32]::SendMessage($hWnd, $WM_LBUTTONUP, [IntPtr]0, $lParamClick)
if($DBLCLK){
# ※ダブルクリックしたい場合は2回目は WM_LBUTTONDBLCLK
[void][Win32]::SendMessage($hWnd, $WM_LBUTTONDBLCLK, [IntPtr]$MK_LBUTTON, $lParamClick)
[void][Win32]::SendMessage($hWnd, $WM_LBUTTONUP, [IntPtr]0, $lParamClick)
}
}
Start-Sleep -Milliseconds 200
}
########
# マウス操作
# 関数:現在のマウス座標(クライアント座標)を取得
function Get-ClientCursorPos($TargethWnd, $x = 0, $y = 0) {
Invoke-Step
if ($TargethWnd) {
$hWnd = $TargethWnd
# ウィンドウ左上のスクリーン座標
$ptScreen = New-Object Win32+POINT
$ptScreen.X = $x
$ptScreen.Y = $y
# スクリーン座標 → クライアント座標
$ptClient = New-Object Win32+POINT
$ptClient.X = $ptScreen.X
$ptClient.Y = $ptScreen.Y
[void][Win32]::ScreenToClient($hWnd, [ref]$ptClient)
return $ptClient
}
}
# 関数:現在のマウス座標を取得
function Get-CursorPos{
$pt = New-Object Win32+POINT
[Win32]::GetCursorPos([ref]$pt) | Out-Null
return $pt
}
# 関数:マウスカーソル移動
function Set-CursorPos($X = 0, $Y = 0) {
Invoke-Step
[Win32]::SetCursorPos($X, $Y)
}
# 関数:左ボタンダウン
function Invoke-MouseLeftButtonDown {
Invoke-Step
[Win32]::mouse_event($MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [UIntPtr]::Zero)
}
# 関数:左ボタンアップ
function Invoke-MouseLeftButtonUp {
Invoke-Step
[Win32]::mouse_event($MOUSEEVENTF_LEFTUP, 0, 0, 0, [UIntPtr]::Zero)
}
# 関数:左ボタンクリック
function Invoke-MouseClick {
Invoke-Step
Invoke-MouseLeftButtonDown
Start-Sleep -Milliseconds 50
Invoke-MouseLeftButtonUp
}
# 関数:左ボタンダブルクリック
function Invoke-MouseDoubleClick {
Invoke-Step
Invoke-MouseClick
Start-Sleep -Milliseconds 50
Invoke-MouseClick
}
##########
# ウィンドウ操作
#
# 関数:コンソールウィンドウをアクティブにする
function Activate-ConsoleWindow {
# SW_RESTOREで最小化解除+表示、次に前面化
$hWnd = [Win32]::GetConsoleWindow()
if ($hWnd -eq [IntPtr]::Zero) {
Write-Verbose "コンソールウィンドウが見つかりません(PowerShell ISEなど)。"
return $false
}
if([Win32]::IsIconic($hWnd)){[void][Win32]::ShowWindow($hWnd, $SW_RESTORE)}
[void][Win32]::SetForegroundWindow($hWnd)
return $true
}
# 関数:座標からウィンドウハンドルを取得
function Get-WindowFromPoint {
param($point)
return [Win32]::WindowFromPoint($point)
"X=$($pt.X) Y=$($pt.Y)"
"HWND = $hwnd"
}
# 関数:指定文字列のウィンドウ一覧配列を返す
function Get-WindowsByTitle {
param(
[string]$titlePattern
)
Invoke-Step
$script:windowsList = @()
$null = [Win32]::EnumWindows({
param($hWnd, $lParam)
if([Win32]::IsWindowVisible($hWnd)){
$title = New-Object System.Text.StringBuilder 256
[Win32]::GetWindowText($hWnd, $title, $title.Capacity)
if ($title.ToString() -match $titlePattern) {
$script:windowsList += [PSCustomObject]@{
Handle = $hWnd
Title = $title.ToString()
}
}
}
return $true
}, [IntPtr]::Zero)
return $script:windowsList
}
# 関数:指定タイトルウィンドウリストを作成する
function Set-CurrentWindowList {
param($str)
$global:currentWindowList = @()
if($str) {
$WINTITLE = $str
$global:currentWindowList = Get-WindowsByTitle $WINTITLE
}
}
# 関数:指定文字列をタイトルに含む最初のウィンドウをアクティブにする
function Set-ActiveWindow {
param($str)
Invoke-Step
if( $null -eq $str) {return}
$maxRetry = 30
for ($i = 0; $i -lt $maxRetry; $i++) {
Invoke-Step
$windows = Get-WindowsByTitle $str
Start-Sleep -Milliseconds 50
if( $global:currentWindowList ) {
$targetWindow = $windows | Where-Object { $_.Handle -notin $global:currentWindowList.Handle } | Select-Object -First 1
} else {
$targetWindow = $windows | Select-Object -First 1
}
if( -not $targetWindow ) { Start-Sleep -Milliseconds 200 }
if ($targetWindow) {
# $targetWindow.Handle が IntPtr
if([Win32]::IsIconic($targetWindow.Handle)){
$null = [Win32]::ShowWindow($targetWindow.Handle, $SW_RESTORE)
}
$null = [Win32]::SetForegroundWindow($targetWindow.Handle)
Start-Sleep -Milliseconds 200
$foreground = [Win32]::GetForegroundWindow()
Write-Host "現在のフォアグラウンドウィンドウ: $foreground"
if ($foreground -eq $targetWindow.Handle) {
Write-Host "指定のウィンドウがアクティブになりました。"
# Start-Sleep -Milliseconds 200
return $true
}
}
Start-Sleep -Seconds 1
}
$global:currentWindowList = @()
Write-Host "指定のウィンドウをアクティブにできませんでした。"
return $false
}
# 関数:ウィンドウ情報カスタムオブジェクトを作成
function Get-WindowObject {
param(
[IntPtr]$Handle
)
# タイトル取得
$titleSb = New-Object System.Text.StringBuilder 256
[Win32]::GetWindowTextW($Handle, $titleSb, $titleSb.Capacity) | Out-Null
# クラス名取得
$classSb = New-Object System.Text.StringBuilder 256
[Win32]::GetClassNameW($Handle, $classSb, $classSb.Capacity) | Out-Null
# プロセスID取得
[uint32]$procid = 0
[Win32]::GetWindowThreadProcessId($Handle, [ref]$procid) | Out-Null
# PowerShell オブジェクトとして返す
[PSCustomObject]@{
Handle = $Handle
Title = $titleSb.ToString()
ClassName = $classSb.ToString()
ProcessId = $procid
Process = (Get-Process -Id $procid -ErrorAction SilentlyContinue)
}
# 例:WindowFromPoint で取得した HWND を渡す
# $hwnd = [Win32]::WindowFromPoint($pt)
# $win = Get-WindowObject -Handle $hwnd
# $win
}