我正在编写 32 位服务应用程序,我希望能够为已登录的用户启动开始菜单项。我确实设法通过模拟用户并使用带有命令行的CreateProcessAsUser启动选定的 .lnk 文件来完成此任务: %windir%\system32\cmd /c " start /b /i "" "<path-to-lnk-file>" "
。它适用于几乎所有的快捷方式,除了来自附件文件夹的系统快捷方式(例如 Sticky Notes.lnk、Snipping Tool.lnk)。在启动截图工具期间,我从 cmd 收到带有此错误的消息框:
Windows 找不到“C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk”。请确保您输入了正确的名称,然后重试。
但是 .lnk 文件就存在于这个目录中!
概括:
- 服务是 32 位的
- 视窗 8 专业版 x64
- 通过用户模拟和使用命令行的 CreateProcessAsUser 启动快捷方式
%windir%\system32\cmd /c " start /b /i "" "<path-to-lnk-file>" "
- 方法几乎适用于开始菜单中的每个快捷方式,除了开始/附件文件夹中的一些快捷方式(并非所有快捷方式,例如 Paint.lnk 可以正常打开)
示例代码:
int launchAppForCurrentLoggedUser() { HANDLE userToken = WTSApiHelper::currentLoggedUserToken(); if (userToken == INVALID_HANDLE_VALUE) { return -1; } //Duplicating token with access TOKEN_DUPLICATE | TOKEN_ALL_ACCESS, //impersonation level SecurityImpersonation and token type TokenPrimary. //Also closing original userToken HANDLE dup = WTSApiHelper::duplicateToken(userToken); if (dup == INVALID_HANDLE_VALUE) { return -1; } int res = -1; uint8 *env = NULL; BOOL succeeded = CreateEnvironmentBlock((LPVOID *)&env, dup, FALSE); if (!succeeded) { Log("failed to get environment variables for user (error 0x%x).", GetLastError()); } PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(PROCESS_INFORMATION)); STARTUPINFOW si; memset(&si, 0, sizeof(STARTUPINFOW)); si.cb = sizeof(STARTUPINFOW); si.lpDesktop = L"winsta0\\Default"; WCHAR params[] = L"/c \" start /b /i \"\" \"C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Accessories\\Snipping Tool.lnk\" \" "; WCHAR cmd[] = L"C:\\Windows\\system32\\cmd.exe"; DWORD flags = env ? CREATE_UNICODE_ENVIRONMENT : 0; succeeded = CreateProcessAsUserW(dup, cmd, params, NULL, NULL, FALSE, flags | CREATE_NO_WINDOW, env, NULL, &si, &pi); if (!succeeded) { Log("cannot launch process for user with error 0x%x.", GetLastError()); } else { nres = 0; } DestroyEnvironmentBlock(env); CloseHandle(dup); return nres; }
我在这里想念什么?