Windows 透過 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer 登錄表鍵值,實作「開始」選單項目的顯示/隱藏原則。這些原則對應群組原則編輯器(gpedit.msc)中的「使用者設定 → 系統管理範本 → 開始選單和工作列」設定。本文示範以 C# 程式碼設定常見隱藏項目,並說明各值名稱對應功能、權限需求、生效時機與撤銷方法。
| 值名稱 (REG_DWORD) | 值 | 隱藏項目 | 群組原則路徑 |
|---|---|---|---|
NoClose | 1 | 「關機」/「登出」/「切換使用者」等電源選項 | 開始選單和工作列 → 移除並禁止存取「關機」命令 |
NoRun | 1 | 「執行...」 (Win+R) | 開始選單和工作列 → 從「開始」選單移除「執行」命令 |
NoFind | 1 | 「搜尋」/「尋找」 | 開始選單和工作列 → 從「開始」選單移除「搜尋」命令 |
NoSetFolders | 1 | 「設定」→「控制台」、「印表機和傳真機」 | 開始選單和工作列 → 從「開始」選單移除「設定」子項目 |
NoSetTaskbar | 1 | 「設定」→「工作列和開始選單屬性」 | 開始選單和工作列 → 從「開始」選單移除「工作列」設定 |
NoLogOff | 1 | 「登出」 | 開始選單和工作列 → 從「開始」選單移除「登出」 |
NoRecentDocsMenu | 1 | 「最近開啟的文件」/「我的文件」 | 開始選單和工作列 → 從「開始」選單移除「最近開啟的文件」 |
NoStartMenuSubFolders | 1 | 所有開始選單子資料夾(僅顯示釘選/常用) | 開始選單和工作列 → 停用開始選單中的子資料夾 |
NoSMMyDocs | 1 | 「我的文件」 | 開始選單和工作列 → 從「開始」選單移除「我的文件」 |
NoSMMyPictures | 1 | 「我的圖片」 | 開始選單和工作列 → 從「開始」選單移除「我的圖片」 |
using System;
using Microsoft.Win32;
public static class StartMenuPolicy
{
private const string PolicyPath = @"Software\Microsoft\Windows\CurrentVersion\Policies\Explorer";
// 要隱藏的項目(值名稱 → 是否啟用)
private static readonly (string Name, bool Enabled)[] Policies = new[]
{
("NoRun", true), // 隱藏「執行」
("NoFind", true), // 隱藏「搜尋」
("NoSetFolders", true), // 隱藏「控制台」、「印表機」
("NoSetTaskbar", false),// 保留「工作列設定」
("NoLogOff", false), // 保留「登出」
("NoClose", false), // 保留「關機」
("NoRecentDocsMenu", false) // 保留「最近文件」
};
public static void Apply()
{
using (var key = Registry.CurrentUser.CreateSubKey(PolicyPath, true)) {
foreach (var (name, enabled) in Policies) {
key.SetValue(name, enabled ? 1 : 0, RegistryValueKind.DWord);
}
}
// 可選:廣播設定變更通知(需 P/Invoke SHChangeNotify 或重啟 Explorer)
Console.WriteLine("開始選單原則已套用,請登出/重新登入或重啟 Explorer 生效。");
}
public static void Revert()
{
using (var key = Registry.CurrentUser.OpenSubKey(PolicyPath, true)) {
if (key == null) return;
foreach (var (name, _) in Policies) {
key.DeleteValue(name, false); // 刪除值即還原預設(顯示)
}
}
Console.WriteLine("開始選單原則已撤銷,請登出/重新登入生效。");
}
public static void PrintCurrent()
{
using (var key = Registry.CurrentUser.OpenSubKey(PolicyPath, false)) {
if (key == null) {
Console.WriteLine("原則鍵不存在(全部預設顯示)。");
return;
}
foreach (var (name, _) in Policies) {
var val = key.GetValue(name);
Console.WriteLine($"{name} = {(val == null ? "未設定(顯示)" : val.Equals(1) ? "隱藏" : "顯示")}");
}
}
}
}
class Program
{
static void Main()
{
Console.WriteLine("=== 目前開始選單原則狀態 ===");
StartMenuPolicy.PrintCurrent();
Console.WriteLine("\n=== 套用隱藏:執行、搜尋、控制台 ===");
StartMenuPolicy.Apply();
Console.WriteLine("\n=== 套用後狀態 ===");
StartMenuPolicy.PrintCurrent();
Console.WriteLine("\n按 Enter 還原...");
Console.ReadLine();
StartMenuPolicy.Revert();
}
}
HKCU 原則需**登出並重新登入**或**重啟 explorer.exe** 才生效。單純重新啟動應用程式無效。HKCU 無需管理員權限,當前使用者即可操作。若需強制所有使用者,寫入 HKLM 同路徑(需管理員)。Policies 子鍵) 由系統定期重新套用,使用者無法透過 UI 覆蓋;偏好設定非強制。本文操作的是原則層級。NoStartMenuSubFolders)可能行為不同,需實測驗證。DeleteValue)或設為 0 均可還原預設顯示。
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, uint fuFlags, uint uTimeout, out IntPtr lpdwResult);
private const uint WM_SETTINGCHANGE = 0x001A;
private const uint HWND_BROADCAST = 0xFFFF;
private const uint SMTO_ABORTIFHUNG = 0x0002;
public static void BroadcastSettingChange()
{
SendMessageTimeout((IntPtr)HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, (IntPtr)0, SMTO_ABORTIFHUNG, 5000, out _);
// 或重啟 Explorer
// Process.Start("explorer.exe"); // 先 Kill 現有 explorer.exe
}
呼順序:修改登錄表 → BroadcastSettingChange() → 部分 UI 即時更新(但開始選單原則通常仍需登出)。
gpedit.msc (本機) 或 GPMC.msc (網域) 設定「使用者設定 → 系統管理範本 → 開始選單和工作列」。透過 Registry.CurrentUser.CreateSubKey 寫入 HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer 下的 REG_DWORD 值,即可程式化控制「開始」選單項目顯示/隱藏。核心值名稱包括 NoRun、NoFind、NoSetFolders 等,生效需登出/重啟 Explorer,受網域 GPO 優先序約束。企業環境優先使用群組原則 (GPO) 統一管理,登錄表程式碼適用於輕量級、動態、無 AD 場景。