通过主窗口标题恢复VirtualBox虚拟机窗口的PowerShell问题
问题:无法通过PowerShell恢复含特定标题的VirtualBox虚拟机窗口
在多虚拟机环境下,Oracle VirtualBox的所有虚拟机进程名均为VirtualBoxVM,无法通过进程名恢复最小化窗口,因此需要借助唯一属性mainWindowTitle来实现。编写的PowerShell脚本执行后无错误提示,但仅出现短暂闪屏,目标窗口仍保持最小化状态。需恢复的窗口标题包含DC2,完整标题为DC2 [Running] - Oracle VM VirtualBox,无论使用完整标题还是部分标题均无效。
原始PowerShell脚本
Clear-Host Function Set-WindowStyle { param ( [Parameter()] [ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', 'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', 'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')] $Style = 'SHOW', [Parameter()] $MainWindowHandle = (Get-Process -Id $pid).MainWindowHandle ) $WindowStates = @{ FORCEMINIMIZE = 11; HIDE = 0 MAXIMIZE = 3; MINIMIZE = 6 RESTORE = 9; SHOW = 5 SHOWDEFAULT = 10; SHOWMAXIMIZED = 3 SHOWMINIMIZED = 2; SHOWMINNOACTIVE = 7 SHOWNA = 8; SHOWNOACTIVATE = 4 SHOWNORMAL = 1 } Write-Verbose ("Set Window Style {1} on handle {0}" -f $MainWindowHandle, $($WindowStates[$style])) $Win32ShowWindowAsync = Add-Type –memberDefinition @" [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); "@ -name "Win32ShowWindowAsync" -namespace Win32Functions –passThru $Win32ShowWindowAsync::ShowWindowAsync($MainWindowHandle, $WindowStates[$Style]) | Out-Null } # Usage # Minimize a running process window #Get-Process -Name Taskmgr | %{Set-WindowStyle MINIMIZE $PSItem.MainWindowHandle} #Get-Process -Name DC2* | %{Set-WindowStyle MINIMIZE $PSItem.MainWindowHandle} # Restore a running process window - the last window called will be topmost #Get-Process -Name DC2 | %{Set-WindowStyle RESTORE $PSItem.MainWindowHandle} #Get-Process | Where-Object {$_.mainWindowTitle} | Format-Table Id, Name, mainWindowtitle -AutoSize Get-Process | Where-Object {$_.MainWindowTitle -Contains "DC2"} | %{Set-WindowStyle RESTORE $PSItem.MainWindowHandle}
当前所有窗口标题输出
PS C:\Users\Admin1> Get-Process | Where-Object {$_.mainWindowTitle} | Format-Table Id, Name, mainWindowtitle -AutoSize Id Name MainWindowTitle -- ---- --------------- 9668 powershell_ise Windows PowerShell ISE 5152 ServerManager Server Manager 2504 VirtualBoxVM CentOS2 [Running] - Oracle VM VirtualBox 4468 VirtualBoxVM WIN10 [Running] - Oracle VM VirtualBox 8812 VirtualBoxVM DC2 [Running] - Oracle VM VirtualBox 9028 VirtualBoxVM MGMT1 [Running] - Oracle VM VirtualBox 10252 VirtualBoxVM CentOS1 [Running] - Oracle VM VirtualBox 10752 VirtualBoxVM ADFS1 [Running] - Oracle VM VirtualBox
解决方案
问题根源
脚本中使用了-Contains操作符,该操作符用于检查集合是否包含指定元素,而非判断字符串是否包含子串。针对单个字符串的子串匹配,应使用-Like或-Match操作符。
修正后的脚本
Clear-Host Function Set-WindowStyle { param ( [Parameter()] [ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', 'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', 'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')] $Style = 'SHOW', [Parameter()] $MainWindowHandle = (Get-Process -Id $pid).MainWindowHandle ) $WindowStates = @{ FORCEMINIMIZE = 11; HIDE = 0 MAXIMIZE = 3; MINIMIZE = 6 RESTORE = 9; SHOW = 5 SHOWDEFAULT = 10; SHOWMAXIMIZED = 3 SHOWMINIMIZED = 2; SHOWMINNOACTIVE = 7 SHOWNA = 8; SHOWNOACTIVATE = 4 SHOWNORMAL = 1 } Write-Verbose ("Set Window Style {1} on handle {0}" -f $MainWindowHandle, $($WindowStates[$style])) $Win32ShowWindowAsync = Add-Type –memberDefinition @" [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); "@ -name "Win32ShowWindowAsync" -namespace Win32Functions –passThru $Win32ShowWindowAsync::ShowWindowAsync($MainWindowHandle, $WindowStates[$Style]) | Out-Null } # 恢复标题包含DC2的VirtualBox窗口 Get-Process | Where-Object {$_.MainWindowTitle -like "*DC2*"} | ForEach-Object {Set-WindowStyle RESTORE $PSItem.MainWindowHandle}
关键修改说明
- 替换
-Contains "DC2"为-Like "*DC2*":-Like支持通配符匹配,*表示任意长度的字符,能准确筛选出标题中包含DC2的窗口。 - 也可使用
-Match "DC2":这是正则表达式匹配,同样能实现子串匹配效果。
验证步骤
先执行以下命令确认是否正确筛选出目标进程:
Get-Process | Where-Object {$_.MainWindowTitle -like "*DC2*"} | Format-Table Id, Name, MainWindowTitle -AutoSize
若能正确显示DC2对应的进程,再执行恢复命令即可生效。
内容的提问来源于stack exchange,提问作者T-Heron
相关产品推荐
相关产品推荐

