最直接方式是遍历注册表中四个核心路径:hklm... un、hkcu... un、hklm...wow6432node... un及hkcu... unonce,再结合shgetfolderpath获取startup文件夹并解析.lnk目标路径。

Windows注册表中读取自启动项最直接的方式
Windows的自启动任务主要存放在注册表几个固定位置,C++程序用RegOpenKeyEx和RegEnumValue就能遍历。关键不是“能不能”,而是“该查哪几个键”——漏掉任意一个,结果就不完整。
必须检查的路径有:
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRunHKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRun-
HKEY_LOCAL_MACHINESOFTWAREWOW6432NodeMicrosoftWindowsCurrentVersionRun(64位系统上32位程序的启动项) -
HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRunOnce(只运行一次,但常被误认为“已执行完就消失”,其实仍存在于注册表)
注意:RunOnce类键值在系统重启后可能被自动删除,但读取时只要还没触发清理,就还在。别跳过它。
使用SHGetFolderPath获取Startup文件夹路径并枚举快捷方式
注册表之外,用户级自启动还大量依赖“启动”文件夹(Start Menu → Startup),这个路径不能硬编码,必须用API动态获取,否则会因系统语言、用户配置不同而失效。
正确做法是调用SHGetFolderPath,传入CSIDL_STARTUP或更现代的CSIDL_COMMON_STARTUP(对应所有用户):
CHAR szPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_STARTUP, NULL, 0, szPath))) {
// 然后用FindFirstFileA遍历.szPath下的.lnk文件
}
常见错误:直接拼接"C:\Users\xxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"——这在中文系统、OneDrive重定向、企业域策略下大概率失败。
还要注意:.lnk文件需用IShellLink接口解析目标路径,不能只读文件名;部分恶意软件会伪装成正常快捷方式,但指向cmd.exe /c start xxx之类间接加载器。
在 Windows 上执行终端命令,或对比 Windows 与 Linux 的 Shell 语法时使用。建议先检测当前 Shell 是 PowerShell 还是 cmd.exe,再给出相应命令……
避免权限不足导致读取失败(尤其是HKLM)
读取HKEY_LOCAL_MACHINE下的自启动项,即使只是查询,某些策略锁定的系统(如教育版、企业组策略启用“阻止访问注册表编辑器”)也会返回ERROR_ACCESS_DENIED。这不是代码写错,而是权限模型限制。
应对策略:
- 用
RegOpenKeyEx时始终检查返回值,对ERROR_ACCESS_DENIED做静默跳过,不抛异常也不中断后续键的读取 - 不要尝试提权(比如加
requireAdministratormanifest)——自启动列表本身是只读信息,没必要以管理员身份运行整个程序 - 优先保证
HKEY_CURRENT_USER和Startup文件夹路径能稳定读到,这两处99%用户都有读权限
额外提醒:UAC虚拟化可能导致32位程序在HKLM下看到的是重定向后的虚拟注册表视图,内容不全。建议统一用64位编译,并显式指定KEY_WOW64_64KEY标志读取原生64位键。
区分“真实启动项”和“干扰项”(如计划任务、服务、浏览器扩展)
用户问的是“自启动任务”,但实际排查时容易把schtasks列出的开机触发任务、sc query state=auto的服务、甚至Chrome的chrome://extensions后台页都混进来。这些不属于传统意义的“自启动任务”。
严格来说,Windows原生定义的自启动入口只有三类:
- 注册表
Run*系列键值(含RunServices等冷门项,但极少用) - Startup文件夹中的可执行文件或快捷方式
- “运行时启动”项(如
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWinlogonUserInit,但修改风险极高,一般工具不展示)
别主动去查Task Scheduler数据库——那属于“计划任务”,触发条件是“登录时”,不是“系统启动时加载”。除非用户明确说“我要所有开机后可能执行的东西”,否则按标准范围收束,不然结果会膨胀且不可控。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










