如何访问Windows开始菜单中列出的所有程序?是否可通过命令行、Windows API或其他方式以编程方式实现?
嘿,刚好我对这个问题挺熟悉的,给你详细说说怎么搞——不管是手动找开始菜单程序的访问路径,还是用编程/命令行自动化获取,都给你安排明白!
一、手动获取开始菜单程序的访问途径
Windows开始菜单里的程序其实都对应着系统目录里的快捷方式(.lnk文件),主要存放在两个位置:
- 公共开始菜单(所有用户可见):
C:\ProgramData\Microsoft\Windows\Start Menu\Programs - 当前用户专属开始菜单:
C:\Users\<你的用户名>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
你可以直接打开这两个目录,找到对应的.lnk文件后右键选择「属性」,在「快捷方式」标签页里就能看到「目标」字段,这就是程序的实际访问路径。
二、编程/命令行方式自动获取
如果需要批量或者自动化获取,下面几种方法都能搞定:
2.1 命令行方式(PowerShell推荐)
CMD本身没法直接解析.lnk的目标路径,用PowerShell会更方便,直接用COM对象就能解析快捷方式:
# 定义开始菜单的两个核心路径 $publicStartMenu = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs" $userStartMenu = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs" # 递归遍历两个目录下所有的.lnk快捷方式 $lnkFiles = Get-ChildItem -Path $publicStartMenu, $userStartMenu -Filter *.lnk -Recurse # 创建WScript.Shell对象来解析快捷方式 $shell = New-Object -ComObject WScript.Shell # 逐个解析并输出结果 foreach ($lnk in $lnkFiles) { $shortcut = $shell.CreateShortcut($lnk.FullName) Write-Host "快捷方式名称: $($lnk.Name)" Write-Host "目标程序路径: $($shortcut.TargetPath)" Write-Host "-------------------------" }
运行这段脚本,就能批量输出所有开始菜单程序的名称和实际访问路径。
2.2 Windows API 方式(原生开发场景)
如果是用C/C++做原生Windows程序开发,可以调用Shell API来获取开始菜单目录并解析快捷方式,核心用到SHGetSpecialFolderPath获取目录,IShellLink接口解析.lnk文件:
#include <windows.h> #include <shlobj.h> #include <iostream> #include <string> #include <filesystem> namespace fs = std::filesystem; // 解析单个快捷方式的目标路径 bool GetShortcutTarget(const wchar_t* lnkPath, std::wstring& targetPath) { IShellLink* pShellLink = nullptr; IPersistFile* pPersistFile = nullptr; HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pShellLink); if (FAILED(hr)) return false; hr = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); if (FAILED(hr)) { pShellLink->Release(); return false; } hr = pPersistFile->Load(lnkPath, STGM_READ); if (FAILED(hr)) { pPersistFile->Release(); pShellLink->Release(); return false; } WCHAR target[MAX_PATH]; hr = pShellLink->GetPath(target, MAX_PATH, nullptr, SLGP_SHORTPATH); if (SUCCEEDED(hr)) { targetPath = target; } pPersistFile->Release(); pShellLink->Release(); return SUCCEEDED(hr); } int main() { CoInitialize(nullptr); // 获取公共开始菜单路径 WCHAR publicStartMenu[MAX_PATH]; SHGetSpecialFolderPath(nullptr, publicStartMenu, CSIDL_COMMON_PROGRAMS, FALSE); std::wcout << L"公共开始菜单路径: " << publicStartMenu << std::endl; // 获取当前用户开始菜单路径 WCHAR userStartMenu[MAX_PATH]; SHGetSpecialFolderPath(nullptr, userStartMenu, CSIDL_PROGRAMS, FALSE); std::wcout << L"用户开始菜单路径: " << userStartMenu << std::endl; // 遍历公共开始菜单的所有.lnk文件 for (const auto& entry : fs::recursive_directory_iterator(publicStartMenu)) { if (entry.path().extension() == L".lnk") { std::wstring target; if (GetShortcutTarget(entry.path().c_str(), target)) { std::wcout << L"快捷方式: " << entry.path().filename() << std::endl; std::wcout << L"目标路径: " << target << std::endl; std::wcout << L"-------------------------" << std::endl; } } } // 遍历用户开始菜单的所有.lnk文件(逻辑同上,可复制上面的循环) CoUninitialize(); return 0; }
注意编译时需要链接shell32.lib,这个方法适合需要深度集成Windows系统的原生开发场景。
2.3 其他编程方式(以Python为例)
Python开发者可以通过win32com.client调用Windows的COM对象,实现和PowerShell类似的功能,先安装依赖库pywin32:
pip install pywin32
然后用这段脚本:
import win32com.client import os # 获取开始菜单的两个核心路径 public_start_menu = os.path.join(os.environ['ProgramData'], 'Microsoft', 'Windows', 'Start Menu', 'Programs') user_start_menu = os.path.join(os.environ['APPDATA'], 'Microsoft', 'Windows', 'Start Menu', 'Programs') # 递归遍历目录下所有的.lnk文件 def collect_lnk_files(root_path): lnk_list = [] for dirpath, _, filenames in os.walk(root_path): for filename in filenames: if filename.endswith('.lnk'): lnk_list.append(os.path.join(dirpath, filename)) return lnk_list # 收集所有快捷方式路径 all_shortcuts = collect_lnk_files(public_start_menu) + collect_lnk_files(user_start_menu) # 解析每个快捷方式的目标路径 shell = win32com.client.Dispatch("WScript.Shell") for lnk_path in all_shortcuts: shortcut = shell.CreateShortCut(lnk_path) print(f"快捷方式名称: {os.path.basename(lnk_path)}") print(f"目标程序路径: {shortcut.TargetPath}") print("-" * 40)
运行后就能批量输出所有开始菜单程序的访问路径了。
内容的提问来源于stack exchange,提问作者BrickByBrick




