简体   繁体   English

SHGetKnownFolderPath 失败并显示 E_ACCESSDENIED

[英]SHGetKnownFolderPath fails with E_ACCESSDENIED

I have a program that calls SHGetKnownFolderPath with FOLDERID_RoamingAppData.我有一个使用 FOLDERID_RoamingAppData 调用 SHGetKnownFolderPath 的程序。

If I start the program by double clicking it, it works ok.如果我通过双击启动程序,它就可以正常工作。

If the program is started by a windows service ( in the current user context ), the function fails with error E_ACCESSDENIED (-2147024891).如果程序由 Windows 服务启动(在当前用户上下文中),该函数将失败并显示错误 E_ACCESSDENIED (-2147024891)。

This is what my code looks like:这是我的代码的样子:

Tstring EasyGetFolderPath(REFKNOWNFOLDERID folderid)
{
    Tstring sPath = _T("");
    PWSTR pszPath = NULL;

    HRESULT hr = SHGetKnownFolderPath(folderid, 0, NULL, &pszPath);

    if (hr == S_OK && pszPath)
    {
        sPath = WStringToTCHAR(pszPath);
        CoTaskMemFree(pszPath);
        return sPath;
    }
    else
    {
        throw HResultException(hr, _T("SHGetKnownFolderPath failed"));
    }
}

Tstring EasyGetUsrAppDataPath()
{
    return EasyGetFolderPath(FOLDERID_RoamingAppData);
}

static TCHAR* WStringToTCHAR(const std::wstring &s)
{
#ifdef UNICODE
    TCHAR *sT = new TCHAR[s.length() + 1];
    _tcscpy_s(sT, s.length() + 1, s.c_str());
    return sT;
#else
    std::string str = WStringToString(s);
    TCHAR *sT = new TCHAR[str.length()+1];
    _tcscpy_s(sT, str.length() + 1, str.c_str());
    return sT;
#endif // UNICODE
}

static std::string WStringToString(const std::wstring& s, bool method = true)
{
    std::string temp;
    temp.assign(s.begin(), s.end());
    return temp;
}

This is the code that starts the process in the current user context: (I've removed the error handling in order to reduce verbosity)这是在当前用户上下文中启动进程的代码:(为了减少冗长,我删除了错误处理)

void StartProcessInCurrentUserContext(const Tstring &sExeName, const Tstringarr &lstParams, const Tstring &sWorkingDir)
{
    ...

    EnableDebugPrivilege();

    errCode = GetProcessByName(_T("explorer.exe"), hProcess);

    if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
    {
        ...
    }

    if (hProcess)
        CloseHandle(hProcess);

    Tstring sCmdLine = ...;

    ...

    // Create the child process. 
    bSuccess = CreateProcessAsUser(hToken, NULL,
        (LPTSTR)sCmdLine.c_str(),            // command line 
        NULL,          // process security attributes 
        NULL,          // primary thread security attributes 
        TRUE,          // handles are inherited 
        0,             // creation flags 
        NULL,          // use parent's environment 
        sWorkingDir.length() > 0 ? (LPCTSTR)sWorkingDir.c_str() : NULL,
        &siStartInfo,  // STARTUPINFO pointer 
        &piProcInfo);  // receives PROCESS_INFORMATION 

    CloseHandle(hToken);

    ...
}

Does anyone know what the problem might be?有谁知道问题可能是什么?

The documentation for SHGetKnownFolderPath says in the discussion of the hToken parameter: SHGetKnownFolderPath的文档hToken参数的讨论中说:

In addition to passing the user's hToken , the registry hive of that specific user must be mounted.除了传递用户的hToken 之外,还必须挂载该特定用户的注册表配置单元。

The documentation for CreateProcessAsUser says CreateProcessAsUser的文档

CreateProcessAsUser does not load the specified user's profile into the HKEY_USERS registry key. CreateProcessAsUser不会将指定用户的配置文件加载到HKEY_USERS注册表项中。

These two paragraphs together explain why your code is not working.这两段一起解释了为什么您的代码不起作用。 Fortunately, the next sentence in the documentation for CreateProcessAsUser explains what you need to do:幸运的是, CreateProcessAsUser文档中的下一句话解释了您需要做什么:

Therefore, to access the information in the HKEY_CURRENT_USER registry key, you must load the user's profile information into HKEY_USERS with the LoadUserProfile function before calling CreateProcessAsUser .因此,要访问HKEY_CURRENT_USER注册表项中的信息,您必须在调用CreateProcessAsUser之前使用LoadUserProfile函数将用户的配置文件信息加载到HKEY_USERS 中 Be sure to call UnloadUserProfile after the new process exits.确保在新进程退出后调用UnloadUserProfile

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 QueryInterface 失败并显示 E_ACCESSDENIED - QueryInterface fails with E_ACCESSDENIED WinbioOpensession 返回 E_ACCESSDENIED? - WinbioOpensession returns E_ACCESSDENIED? directX directInput键盘抛出E_accessdenied - directX directInput Keyboard throws E_accessdenied 在CoCreateInstance上的E_ACCESSDENIED,它曾经在这里工作 - E_ACCESSDENIED on CoCreateInstance, where it used to work 当使用相同的 HWND 时,D3D11CreateDeviceAndSwapChain 失败并显示 E_ACCESSDENIED - D3D11CreateDeviceAndSwapChain Fails With E_ACCESSDENIED When Using Same HWND 调用CryptImportKey时E_ACCESSDENIED(HR 0x80070005) - E_ACCESSDENIED (HR 0x80070005) on CryptImportKey call C ++中的任务管理器:任务注册时E_ACCESSDENIED的HRESULT - Task Manager in C++: HRESULT of E_ACCESSDENIED on task registration 为什么在Win Service中调用ShellExecute会导致无关的传入COM连接失败并显示E_ACCESSDENIED? - Why does calling ShellExecute in Win Service cause unrelated incoming COM connections to fail with E_ACCESSDENIED? 从.NET附加到COM服务器中的事件时,E_ACCESSDENIED异常 - E_ACCESSDENIED exception when attaching to an event in a COM server from .NET imediacontrol-> run在C ++中运行图形时返回E_ACCESSDENIED - imediacontrol->run returns E_ACCESSDENIED while running the graph in c++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM