昨天我又被這個問題坑了一次。筆電關蓋放進背包,騎車到咖啡廳,打開包準備開工——機器燙手、電量歸零、已經自動關機。整個下午的計畫泡湯。

這不是第一次。我的 Steam Deck 也中過同樣的招:放包裡沒事,拿出來卻發燙、掉電掉得莫名其妙。元凶我早就懷疑過,這次決定把它揪出來釘死:藍牙滑鼠在背包裡被擠壓、滾動,被系統當成「使用者想喚醒電腦」的訊號,於是它就在密閉的包包裡偷偷醒過來,自己跑了一整個下午。

罪魁禍首:藍牙裝置的喚醒權限

Windows 預設讓不少連接的裝置具有「喚醒電腦」的權限,滑鼠和鍵盤尤其常見。這在桌機上有用——按一下滑鼠就把睡眠的機器叫起來。但對天天把筆電丟進背包移動的人來說,它是個災難。

藍牙滑鼠在包裡稍微移動或被按到,系統就判定該醒了。結果電腦在沒有散熱空間的背包裡開機運轉,電力白白燒掉,長時間悶著還可能因為過熱傷到硬體。

要解決它,得先搞清楚一件事:到底哪些裝置現在「有權限」叫醒你的電腦。

第一步:先看清楚誰能喚醒電腦

別急著寫一大段腳本掃全部裝置。Windows 內建的 powercfg 有一個指令,直接列出當下被授權喚醒系統的裝置清單,而且這份清單通常很短:

1
powercfg /devicequery wake_armed

跑完你會看到類似這樣的輸出(裝置名稱依你的硬體而定):

1
2
3
HID-compliant mouse (002)
Logitech MX Master 3
Intel(R) Wireless Bluetooth(R)

這份清單就是真正的問題來源。不在清單上的裝置根本沒有喚醒權限,不用碰。我第一次跑的時候才發現,能叫醒我筆電的其實只有兩個——藍牙滑鼠和藍牙介面卡,根本不需要動到其他幾十個裝置。

第二步:用 powercfg 精準關掉它

知道名字之後,停用就是一行:

1
2
# 名稱要跟 wake_armed 列出來的「完全一致」,含括號編號,用引號包起來
powercfg /devicedisablewake "Logitech MX Master 3"

要注意兩件事,這是我踩過的坑:

  • 必須用系統管理員身分執行 PowerShell。 一般權限跑會直接吐 You do not have the permission to enable or disable device wake
  • 裝置名稱要跟 wake_armed 列出來的字串一字不差,包含結尾的 (002) 這種編號。複製貼上最保險,別自己手打。

如果哪天想反悔、把喚醒權限加回來,對應指令是 powercfg /deviceenablewake "<裝置名稱>"

對大多數人來說,powercfg 這條路就夠了:列出來、挑出藍牙那幾個、一個個 disable。它是官方工具、最可靠,也不會誤傷其他裝置。

進階:用 WMI 批次處理藍牙裝置

如果你像我一樣常常換不同的藍牙滑鼠、鍵盤,每次重新配對後又得重跑一遍 powercfg,那可以走 WMI 這條路,直接針對「所有藍牙裝置」批次關閉喚醒。

喚醒權限在驅動層對應的是 root\wmi 命名空間下的 MSPower_DeviceWakeEnable 類別,它有一個 Enable 屬性——$true 是允許喚醒,$false 是停用。做法是先用 Get-PnpDevice 抓出所有藍牙裝置的 PnP ID,再去 WMI 裡比對對應的實例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 需以系統管理員身分執行
# 取得所有目前在線的藍牙裝置
$bluetoothDevices = Get-PnpDevice -Class Bluetooth -PresentOnly

# 一次抓出所有可設定喚醒的 WMI 實例
$wakeInstances = Get-CimInstance -Namespace root/wmi -ClassName MSPower_DeviceWakeEnable

foreach ($device in $bluetoothDevices) {
$pnpId = $device.InstanceId

# 關鍵:InstanceName 的大小寫與反斜線格式和 PnP ID 不一定一致,
# 用 [regex]::escape 比對才不會因為 \ 被當成特殊字元而漏掉。
$match = $wakeInstances | Where-Object {
$_.InstanceName -match [regex]::escape($pnpId)
}

if ($match) {
foreach ($inst in $match) {
$inst.Enable = $false
Set-CimInstance -InputObject $inst
Write-Host "已關閉喚醒:$($device.FriendlyName)" -ForegroundColor Yellow
}
}
}

Write-Host "藍牙裝置喚醒權限處理完成" -ForegroundColor Green

這裡有個我繞了一段路才搞懂的細節:MSPower_DeviceWakeEnableInstanceName 通常是大寫、結尾還會多帶一個 _0,而 Get-PnpDevice 給的 InstanceId 是含反斜線的原始格式,兩者直接用 LIKE '%...%' 比常常對不上。[regex]::escape($pnpId) 把反斜線等特殊字元跳脫掉,搭配 -match 才穩。如果你看到腳本跑完卻一個裝置都沒命中,十之八九就是卡在這。

這個腳本有兩個會漏抓的情況,務必知道。第一,Get-PnpDevice -Class Bluetooth 抓的是「藍牙」類別的節點,但有些藍牙滑鼠/鍵盤的喚醒能力其實掛在它的 HID 層子節點上(InstanceId 是 HID\... 開頭、跟藍牙節點的 BTHENUM\... 對不起來),這種就比對不到、會被跳過。第二,MSPower_DeviceWakeEnable 只涵蓋驅動有暴露這個 WMI 介面的裝置,少數裝置根本查不到實例。所以跑完一定要用下一步的 wake_armed 再確認一次,還留在清單上的,就回頭用 powercfg /devicedisablewake 一個個補。WMI 這條是「能批次處理掉大部分」,不是「保證全部」。

如果你偏好舊式的 Get-WmiObject,邏輯一樣,只是提交改動用的是 psbase.Put()

1
2
3
4
$inst = Get-WmiObject -Namespace root\wmi -Class MSPower_DeviceWakeEnable |
Where-Object { $_.InstanceName -match [regex]::escape($pnpId) }
$inst.Enable = $false
$inst.psbase.Put()

確認設定真的生效

改完別憑感覺,回頭再跑一次第一步那條指令:

1
powercfg /devicequery wake_armed

如果處理成功,剛剛關掉的藍牙裝置就不會再出現在這份清單裡。清單變短,甚至空了,就代表沒有任何裝置能在背包裡偷偷叫醒你的電腦了。這是最直接的驗證——比去查每個裝置的 Enable 屬性快得多。

不想碰命令列?裝置管理員一樣能設

如果你不熟命令列,圖形介面也做得到,只是要一個一個點:

  1. Win + X,選「裝置管理員」
  2. 展開「藍牙」分類
  3. 對你的藍牙滑鼠(或其他裝置)按右鍵,選「內容」
  4. 切到「電源管理」分頁
  5. 取消勾選「允許這個裝置喚醒電腦」
  6. 按「確定」
  7. 對每個藍牙裝置重複一次

如果某個裝置的內容裡找不到「電源管理」分頁,代表它的驅動根本沒有暴露喚醒設定——這種裝置本來就不會出現在 wake_armed 清單裡,不用理它。

裝置不多的話,這方法其實夠快,也最不容易出錯。要批次或常常重設才值得寫腳本。

成果

設定完到現在,筆電再也沒在背包裡自己開過機。滑鼠在包裡怎麼滾、按鍵怎麼被壓,機器都安安靜靜睡著。我也順手把 Steam Deck 的同類設定處理掉,兩台帶出門的裝置都不再背著我偷偷耗電。

說真的,這問題小到很容易被當成「電池本來就不耐」而忽略,但對天天背筆電移動的人,差別是「到了地方能直接開工」還是「先找插座續命半小時」。powercfg /devicequery wake_armed 這一條指令,是我覺得最該先記下來的——先看清楚誰有權限,剩下的都好辦。