You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因

  1. 空引用异常根源:$syncHash.Window在窗口Load事件中赋值,但[System.Windows.Forms.Application]::Run()调用时,窗口还未触发Load事件,此时$syncHash.Window为null,直接引发报错。
  2. 热键捕获无效:全局注册的热键不会触发普通KeyDown事件,必须通过处理WM_HOTKEY系统消息才能捕获。
  3. 句柄创建时机问题:$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:47:18