Electron小工具开发:检测全屏应用以控制唤出逻辑(PowerShell失效)
检测系统全屏应用,控制Electron工具唤出逻辑
我正在开发一款Electron小工具,按下Ctrl+Space组合键即可唤出显示。需求是仅当系统中没有应用处于全屏运行状态时,该工具才能被唤出。我曾尝试用PowerShell实现检测逻辑,但方案无法正常工作,原代码如下:
const { exec } = require('child_process') function isFullscreenAppRunning() { return new Promise((resolve, reject) => { const script = ` function Is-AppFullScreen { param( [Parameter(Mandatory = $true)] [string] $ProcessName ) # Get main screen resolution $screenWidth = (Get-Screen).WorkingArea.Width $screenHeight = (Get-Screen).WorkingArea.Height # Get window of the process $window = Get-Process -Name $ProcessName | Where-Object {$_.MainWindowTitle -ne $null} | Select-Object -ExpandProperty MainWindowHandle if ($window) { # Get window dimensions (accounting for borders) $windowRect = [System.Drawing.Rectangle]::FromLTRB((Get-Window -Handle $window).Left, (Get-Window -Handle $window).Top, (Get-Window -Handle $window).Right, (Get-Window -Handle $window).Bottom) $windowWidth = $windowRect.Width - (Get-Window -Handle $window).BorderWidth $windowHeight = $windowRect.Height - (Get-Window -Handle $window).BorderHeight # Check if window dimensions match screen resolution (considering potential rounding errors) return ($windowWidth -eq $screenWidth -and $windowHeight -eq $screenHeight) } else { # Process not found or no main window return $false } } # Check all processes with a main window title $isAnyAppFullScreen = $false Get-Process | Where-Object {$_.MainWindowTitle -ne $null} | ForEach-Object { $processName = $_.Name if (Is-AppFullScreen -ProcessName $processName) { $isAnyAppFullScreen = $true # Exit loop once a fullscreen app is found (optional for performance) break } } # Return true if any app is fullscreen, false otherwise return $isAnyAppFullScreen ` exec(`powershell -command "${script}"`, (err, stdout, stderr) => { if (err) { reject(err) return } resolve(stdout.trim() === 'True') }) }) }
原方案问题分析
- 依赖非原生命令:
Get-Screen和Get-Window属于第三方PowerShell模块(如PSScriptTools),未安装时会直接报错。 - 全屏判断逻辑错误:使用
WorkingArea(排除任务栏的屏幕区域)作为判断基准,而真正的全屏应用会覆盖整个显示器(包括任务栏),导致误判。 - 进程名匹配风险:通过进程名获取窗口句柄,若存在同名进程,可能获取错误的窗口信息。
修复后的解决方案
方案1:基于原生Windows API的PowerShell脚本
改用Windows原生API获取窗口和显示器信息,无需额外安装模块,判断逻辑更准确:
const { exec } = require('child_process'); function isFullscreenAppRunning() { return new Promise((resolve, reject) => { const script = ` Add-Type @" using System; using System.Runtime.InteropServices; public class WindowInfo { [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi); [DllImport("user32.dll")] public static extern IntPtr MonitorFromWindow(IntPtr hWnd, uint dwFlags); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [StructLayout(LayoutKind.Sequential)] public struct MONITORINFO { public uint cbSize; public RECT rcMonitor; public RECT rcWork; public uint dwFlags; } [DllImport("user32.dll")] public static extern uint GetWindowLong(IntPtr hWnd, int nIndex); public const int GWL_STYLE = -16; public const uint WS_MAXIMIZE = 0x01000000; } "@ function Test-WindowIsFullScreen { param([IntPtr]$hWnd) # 先判断窗口是否处于最大化状态 $style = [WindowInfo]::GetWindowLong($hWnd, [WindowInfo]::GWL_STYLE) if (-not ($style -band [WindowInfo]::WS_MAXIMIZE)) { return $false } # 获取窗口所在显示器的完整区域(包括任务栏) $monitor = [WindowInfo]::MonitorFromWindow($hWnd, 0) $monitorInfo = New-Object WindowInfo+MONITORINFO $monitorInfo.cbSize = [System.Runtime.InteropServices.Marshal]::SizeOf($monitorInfo) [WindowInfo]::GetMonitorInfo($monitor, [ref]$monitorInfo) # 获取窗口的实际位置和大小 $windowRect = New-Object WindowInfo+RECT [WindowInfo]::GetWindowRect($hWnd, [ref]$windowRect) # 判断窗口是否完全覆盖显示器的整个区域 return ($windowRect.Left -eq $monitorInfo.rcMonitor.Left -and $windowRect.Top -eq $monitorInfo.rcMonitor.Top -and $windowRect.Right -eq $monitorInfo.rcMonitor.Right -and $windowRect.Bottom -eq $monitorInfo.rcMonitor.Bottom) } $isFullscreen = $false # 遍历所有拥有有效窗口句柄的进程 Get-Process | Where-Object { $_.MainWindowHandle -ne 0 } | ForEach-Object { if (Test-WindowIsFullScreen $_.MainWindowHandle) { $isFullscreen = $true break } } $isFullscreen `; exec(`powershell -command "${script}"`, (err, stdout, stderr) => { if (err) { reject(err); return; } resolve(stdout.trim() === 'True'); }); }); } // 快捷键唤出逻辑示例 async function toggleToolWindow() { const hasFullscreenApp = await isFullscreenAppRunning(); if (!hasFullscreenApp) { // 这里替换为你的Electron窗口显示逻辑 console.log('唤出工具窗口'); } else { console.log('检测到全屏应用,不唤出工具'); } } // 注册Ctrl+Space快捷键 const { globalShortcut } = require('electron'); globalShortcut.register('Ctrl+Space', toggleToolWindow);
方案2:使用Node.js原生库(跨平台可选)
如果需要跨平台支持,可以使用windows-management(Windows)或Electron内置screen模块结合窗口检测库:
- 安装依赖:
npm install windows-management - 简化检测逻辑:
const { getAllWindows } = require('windows-management'); const { screen } = require('electron'); function isFullscreenAppRunning() { const displays = screen.getAllDisplays(); for (const window of getAllWindows()) { if (window.isFullscreen) { return true; } // 额外判断最大化窗口是否覆盖整个显示器 for (const display of displays) { if (window.x === display.bounds.x && window.y === display.bounds.y && window.width === display.bounds.width && window.height === display.bounds.height) { return true; } } } return false; } // 快捷键逻辑同方案1
内容的提问来源于stack exchange,提问作者ivox
相关产品推荐
相关产品推荐

