首页 > 解决方案 > 通过服务启动进程后来自 SHGetKnownFolderPath 的错误 0x80070005

问题描述

我使用下面的代码来获取 appdata 文件夹。通常它可以工作,但如果我使用与此类似的方式通过服务启动相同的进程,我会收到错误0x80070005,这意味着Access Denied.

HRESULT result;
if ((result = SHGetKnownFolderPath(
    FOLDERID_RoamingAppData,
    NULL,
    NULL,
    &appdate)) != S_OK)
{
    std::cout << result << std::endl

    return false;
}

创建进程的函数是

if (!CreateProcessAsUser(
        token,
        executablePath,
        executableName,
        NULL,
        NULL,
        FALSE,
        NORMAL_PRIORITY_CLASS,
        NULL,
        0,
        &startupInfo,
        &processInformation))
    {
        SHOW_SERVICE_ERROR;
    }

我在互联网上没有找到与此相关的任何内容。任何人都可以帮忙吗?

标签: c++winapiserviceprocess

解决方案


您没有将lpEnvironment参数传递给CreateProcess调用的错误。

lpEnvironment [输入,可选]

指向新进程的环境块的指针。如果此参数为NULL,则新进程使用调用进程的环境。

结果子进程使用调用进程的环境。这有什么影响FOLDERID_RoamingAppData?在解决期间FOLDERID_RoamingAppData- 我们通常得到%USERPROFILE%\AppData\Roaming- 最终结果将取决于%USERPROFILE%. 在您的情况下-它将从 service( LocalSystem) 继承并且看起来像C:\WINDOWS\system32\config\systemprofile-所以最终路径必须看起来像C:\WINDOWS\system32\config\systemprofile\AppData\Roaming。在将此路径返回给调用者之前 - 系统检查路径是否存在 - 调用GetFileAttributes。在这里它失败了(由于安全许可) - 最后一个错误 - 5 - ERROR_ACCESS_DENIED。和 api 最终返回HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)80070005.

结论 - 在调用中CreateProcessAsUser使用指向由 . 返回的环境块的指针CreateEnvironmentBlock。并稍后释放此块DestroyEnvironmentBlock。也不要忘记CREATE_UNICODE_ENVIRONMENT通话中的标志CreateProcessAsUser

您的错误也可以通过下一个代码在本地(非提升)过程中轻松重现:

SetEnvironmentVariableW(L"USERPROFILE", L"C:\\WINDOWS\\system32\\config\\systemprofile");
PWSTR appdate;
HRESULT result;
if ((result = SHGetKnownFolderPath(
    FOLDERID_RoamingAppData,
    NULL,
    NULL,
    &appdate)) == S_OK)
{
    CoTaskMemFree(appdate);
}

如果我们将设置无效路径USERPROFILE- 我们得到80070003错误 -HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)


推荐阅读