Windows 提供 `GetSystemMetrics` 系統指標查詢 API,參數 `SM_CLEANBOOT` (值 67) 專門用於檢測啟動模式。此為**唯一官方文件化**的啟動模式檢測方法,支援 Windows 95 至 Windows 11 全版本。
| 返回值 | 啟動模式 | 特徵 | 典型用途 |
|---|---|---|---|
| 0 | 正常模式 | 完整驅動、服務、網路、圖形介面 | 標準應用程式執行環境 |
| 1 | 安全模式 | 最小驅動集、無網路、標準 VGA 顯示、僅核心服務 | 疑難排解、病毒掃描、驅動衝突修復 |
| 2 | 含網路安全模式 | 安全模式基礎上啟用網路驅動與服務 | 遠端管理、網路修復、域環境疑難排解 |
void __fastcall TForm1::Button1Click(TObject* Sender) {
int bootMode = GetSystemMetrics(SM_CLEANBOOT);
AnsiString msg;
switch (bootMode) {
case 0: msg = "正常模式啟動"; break;
case 1: msg = "安全模式啟動"; break;
case 2: msg = "安全模式啟動,但帶網路功能"; break;
default: msg = "未知啟動模式 (" + IntToStr(bootMode) + ")"; break;
}
ShowMessage(msg);
// 實際應用:安全模式下禁用特定功能
if (bootMode != 0) {
// 禁用多媒體、網路進階功能、硬體加速等
MediaPlayer1->Enabled = false;
NetworkComponent->Enabled = false;
}
}
#pragma startup CheckBootMode 33 // 早期執行優先級
void CheckBootMode() {
int mode = GetSystemMetrics(SM_CLEANBOOT);
if (mode != 0) {
// 記錄事件日誌
HANDLE hEventLog = RegisterEventSource(NULL, "MyApplication");
if (hEventLog) {
char* strings[] = { "Application blocked in Safe Mode" };
ReportEvent(hEventLog, EVENTLOG_WARNING_TYPE, 0, 0, NULL, 1, 0, (const char**)strings, NULL);
DeregisterEventSource(hEventLog);
}
// 彈出對話框並退出
MessageBox(NULL,
"偵測到安全模式啟動,本程式需要完整系統環境執行。\n請在正常模式下重新啟動電腦後再試。",
"啟動模式不支援", MB_OK | MB_ICONWARNING | MB_SYSTEMMODAL);
ExitProcess(0);
}
}
bool IsSafeModeRegistry() {
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\SafeBoot", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
DWORD type, size = 256;
char value[256];
// OptionValue = "Minimal" 或 "Network"
if (RegQueryValueEx(hKey, "OptionValue", NULL, &type, (LPBYTE)value, &size) == ERROR_SUCCESS) {
RegCloseKey(hKey);
return (strcmp(value, "Minimal") == 0 || strcmp(value, "Network") == 0);
}
RegCloseKey(hKey);
}
return false;
}
bool IsSafeModeWMI() {
// 需引入 wbemidl.h, 鏈接 wbemuuid.lib
// SELECT BootState FROM Win32_ComputerSystem
// BootState = "Safe mode" / "Safe mode with Networking" / "Normal"
// 實作略 (需 COM 初始化、IWbemLocator、IWbemServices、查詢執行)
}
bool IsLikelySafeMode() {
// 安全模式下通常停用的服務
const char* criticalServices[] = { "Themes", "AudioSrv", "W32Time", "wuauserv" };
SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!hSCM) return false;
for (const char* svc : criticalServices) {
SC_HANDLE hSvc = OpenService(hSCM, svc, SERVICE_QUERY_STATUS);
if (hSvc) {
SERVICE_STATUS_PROCESS ssp;
DWORD bytesNeeded;
if (QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(ssp), &bytesNeeded)) {
if (ssp.dwCurrentState == SERVICE_RUNNING) {
CloseServiceHandle(hSvc);
CloseServiceHandle(hSCM);
return false; // 關鍵服務正在運行,極可能是正常模式
}
}
CloseServiceHandle(hSvc);
}
}
CloseServiceHandle(hSCM);
return true; // 多數關鍵服務未運行
}
| 場景 | 處理策略 |
|---|---|
| 硬體加速依賴應用 (遊戲、CAD、視訊編輯) | 安全模式下顯示警告並退出,或降級為軟體渲染模式 |
| 網路依賴服務 (雲端同步、授權驗證) | 僅在模式 2 (含網路安全模式) 允許網路功能,模式 1 禁用 |
| 系統工具 (註冊表清理、啟動項管理) | 安全模式下提供精簡功能集,避免誤刪關鍵項目 |
| 企業部署軟體 | 記錄啟動模式至事件日誌/遙測,供 IT 稽核 |
`GetSystemMetrics(SM_CLEANBOOT)` 是檢測 Windows 啟動模式的**標準、可靠、跨版本**方法。結合登錄、WMI、服務狀態等備援檢測,可構建健壯的環境適應性邏輯。開發者應在程式啟動早期 (如專案啟動順序優先級) 執行檢測,根據模式動態調整功能可用性、記錄診斷資訊、引導使用者切換至適當環境,提升軟體穩定度與用戶體驗。