Windows 11 PowerShell热键拦截脚本空引用错误求助
PowerShell热键脚本空引用异常排查修复
错误信息
Exception calling "Run" with "1" argument(s): "Object reference not set to an instance of an object."
At C:\Users\desktop-test\hotkey3.ps1:65 char:1
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : NullReferenceException
原脚本内容
# Define constants $MOD_CONTROL = 0x0002 $MOD_SHIFT = 0x0004 $VK_K = 0x4B # Load necessary types Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; public static class Hotkey { [DllImport("user32.dll", SetLastError = true)] public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); [DllImport("user32.dll", SetLastError = true)] public static extern bool UnregisterHotKey(IntPtr hWnd, int id); public const int WM_HOTKEY = 0x0312; } "@ -Language CSharp # Create a hidden window for message processing Add-Type -AssemblyName System.Windows.Forms $window = New-Object System.Windows.Forms.Form $window.ShowInTaskbar = $false $window.WindowState = [System.Windows.Forms.FormWindowState]::Minimized $window.MinimizeBox = $false $window.MaximizeBox = $false $window.Visible = $false # Register the hotkey [void][Hotkey]::RegisterHotKey($window.Handle, 1, $MOD_CONTROL -bor $MOD_SHIFT, $VK_K) # Define the action on hotkey press $window.Add_KeyDown({ # Your code here, e.g.: Write-Host "Hotkey pressed!" }) # Unregister the hotkey when the window is closed $window.Add_FormClosed({ [void][Hotkey]::UnregisterHotKey($window.Handle, 1) }) # Display the hidden window $syncHash = [hashtable]::Synchronized(@{}) # Wait for the WM_HOTKEY message $window.Add_Load({ $syncHash.Window = $window $window.Activate() [void][System.Windows.Forms.Application]::DoEvents() }) # Run [System.Windows.Forms.Application]::Run($syncHash.Window)
启动命令
powershell.exe -ExecutionPolicy Bypass -File \Users\supercobra\OneDrive\Desktop\hotkeystack.ps1
问题原因
- 空引用异常根源:
$syncHash.Window在窗口Load事件中赋值,但[System.Windows.Forms.Application]::Run()调用时,窗口还未触发Load事件,此时$syncHash.Window为null,直接引发报错。 - 热键捕获无效:全局注册的热键不会触发普通
KeyDown事件,必须通过处理WM_HOTKEY系统消息才能捕获。 - 句柄创建时机问题:
$window.Handle在窗口未完成初始化时可能未生成,直接用它注册热键存在失败风险。
修复后的脚本
# Define constants $MOD_CONTROL = 0x0002 $MOD_SHIFT = 0x0004 $VK_K = 0x4B # Load necessary types Add-Type -TypeDefinition @" using System; using System.Runtime.InteropServices; using System.Windows.Forms; public static class Hotkey { [DllImport("user32.dll", SetLastError = true)] public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); [DllImport("user32.dll", SetLastError = true)] public static extern bool UnregisterHotKey(IntPtr hWnd, int id); public const int WM_HOTKEY = 0x0312; } public class HotkeyForm : Form { protected override void WndProc(ref Message m) { if (m.Msg == Hotkey.WM_HOTKEY) { int id = m.WParam.ToInt32(); if (id == 1) { OnHotkeyPressed(EventArgs.Empty); } } base.WndProc(ref m); } public event EventHandler HotkeyPressed; protected virtual void OnHotkeyPressed(EventArgs e) { HotkeyPressed?.Invoke(this, e); } } "@ -Language CSharp # Create custom hidden window Add-Type -AssemblyName System.Windows.Forms $window = New-Object HotkeyForm $window.ShowInTaskbar = $false $window.WindowState = [System.Windows.Forms.FormWindowState]::Minimized $window.MinimizeBox = $false $window.MaximizeBox = $false $window.Visible = $false # Ensure window handle is created $null = $window.Handle # Register the hotkey if (-not [Hotkey]::RegisterHotKey($window.Handle, 1, $MOD_CONTROL -bor $MOD_SHIFT, $VK_K)) { Write-Error "Failed to register hotkey, error code: $([Runtime.InteropServices.Marshal]::GetLastWin32Error())" exit 1 } # Define action on hotkey press $window.Add_HotkeyPressed({ Write-Host "Hotkey pressed!" }) # Unregister hotkey on close $window.Add_FormClosed({ [void][Hotkey]::UnregisterHotKey($window.Handle, 1) }) # Run the application message loop [System.Windows.Forms.Application]::Run($window)
关键修改说明
- 自定义
HotkeyForm类并重写WndProc方法,专门处理WM_HOTKEY系统消息,确保全局热键能被正确捕获。 - 提前触发窗口句柄创建(
$null = $window.Handle),避免注册热键时因句柄无效导致失败。 - 直接使用
$window作为Application::Run的参数,移除多余的syncHash逻辑,从根源解决空引用问题。 - 添加热键注册失败的错误提示,便于快速排查注册环节的问题。
内容的提问来源于stack exchange,提问作者supercobra
相关产品推荐
相关产品推荐

