是否有本地化安全的方法来获取 SYSTEM 帐户的 AppData 目录?

Posted

技术标签:

【中文标题】是否有本地化安全的方法来获取 SYSTEM 帐户的 AppData 目录?【英文标题】:Is there a localization-safe way to get the SYSTEM account's AppData directory? 【发布时间】:2019-04-16 18:39:49 【问题描述】:

我知道我可以使用GetSystemDirectory() 来获取C:\Windows\System32 的目录,但我想知道是否有办法在下面获取此目录路径,无论操作系统如何本地化或我是否以普通用户或系统帐户:

C:\Windows\System32\config\systemprofile\AppData\Local\TEMP

或者至少到C:\Windows\System32\config\systemprofile\AppData

我尝试在SHGetFolderPath() 中使用SHGFP_TYPE_DEFAULT 而不是SHGFP_TYPE_CURRENT 选项,但这将返回当前正在运行的用户目录,而不是在不作为SYSTEM 运行时返回SYSTEM。

void GetUserLocalTempPath(std::wstring& input_parameter) 
    HWND folder_handle =  0 ;
    WCHAR temp_path[MAX_PATH];
    auto get_folder = SHGetFolderPath(
        folder_handle, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_DEFAULT, temp_path
    );
    if (get_folder == S_OK) 
        input_parameter = static_cast<const wchar_t*>(temp_path);
        input_parameter.append(L"\\TEMP");
        CloseHandle(folder_handle);
    

【问题讨论】:

不清楚什么是问题/问题。您可以按原样获取文件路径 不清楚您对@RbMm 的不清楚之处。您是说本地化无关紧要,并且始终使用英语吗? 但是函数返回给你的文件系统路径。照原样。你想要什么本地化? 不,正确的方法是使用 CSIDL_LOCAL_APPDATASHGetKnownFolderPath 和带有本地系统令牌的 FOLDERID_LocalAppData 或运行/模拟本地系统时。你不需要硬编码L"\\config\\systemprofile\\AppData" SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, SHGFP_TYPE_CURRENT, temp_path) 例如(如果您以 LocalSystem 身份运行)您如何使用 folder_handle 不正确 - 这是 hwnd 并且仅在参数中。 CloseHandle(folder_handle);当然错了 【参考方案1】:

您需要在SYSTEM 帐户下运行一个进程才能查询SYSTEM 配置文件。

创建一个以SYSTEM 运行的单独服务。需要时,让它调用SHGetFolderPath(CSIDL_LOCAL_APPDATA)SHGetKnownFolderPath(FOLDERID_LocalAppData),为用户令牌指定NULL,以便查询调用用户(即SYSTEM)的配置文件(或者,只需使用GetTempPath(),其中will also work in this context) .

然后,该服务可以通过您想要的任何与会话无关的 IPC 机制(管道、套接字等)将该路径传递回您的主应用程序。

附注:

在将temp_path 分配给input_parameter 时,您不需要进行类型转换。 temp_path 将隐式衰减wchar_t* 指针,该指针可以按原样传递给std::wstring::operator=() 作为输入的const wchar_t* 指针。

而不是手动使用input_parameter.append(L"\\TEMP")(如果您使用GetTempPath(),则根本不需要),您应该考虑使用PathCchCombineEx()(或相关)或SHGetFolderPathAndSubDir()。让操作系统为您处理附加内容。

您使用 HWND 作为输入调用 CloseHandle(),这是错误的,因为它需要 HANDLE 代替(但在您的情况下这是一个无操作,因为 HWND 为 NULL,所以只需完全删除CloseHandle())。显然,您没有在启用STRICT Type Checking 的情况下编译您的项目,否则编译器会阻止将HWND 传递给HANDLE 参数。

【讨论】:

感谢您提及STRICT!我会检查一下:)【参考方案2】:

Remy Lebeau's answer 是以编程方式执行此操作的正确方法。但是,它可能超出 的要求;如果您需要此功能的原因不需要多代操作系统支持,您可能不想跳过所有这些障碍。因此,如果您使用的是 Windows 10,那么现在执行此操作似乎是安全的。也就是说,我不推荐它,因为它的基本缺点。这只是一个简单的草率解决方法,因此使用风险自负

我没有任何关于这个潜在解决方案寿命的支持文档,只有轶事反馈和一些个人测试。

我从几个人那里听说重要的操作系统系统目录没有本地化。我将 Windows 10 Pro Japanese 映像作为虚拟机安装到 Hyper-V 主机上。将字符串 C:\Windows\System32\config\systemprofile\AppData 粘贴并输入到日语资源管理器地址栏中工作正常,如下所示, 这里的要点是,在您获得系统目录的值之后(我们不能假设C:\WINODWS\system32),您应该能够用简单的英语对其余部分进行硬编码。这是一个可以为您完成此任务的示例应用程序:

#define STRICT
#include <Windows.h>
#include <wchar.h>
#include <memory>

int wmain()

    static constexpr const wchar_t * SystemProfileAppData_RemainingPath
        = L"\\config\\systemprofile\\AppData";

    wchar_t system_path_buffer[MAX_PATH];
    const std::size_t winapi_worked = GetSystemDirectory(system_path_buffer, MAX_PATH);

    if (winapi_worked) 
        const std::size_t system32_offset = wcsnlen_s(system_path_buffer, MAX_PATH);
        const std::size_t appdata_offset  = wcsnlen_s(SystemProfileAppData_RemainingPath, MAX_PATH);
        const std::size_t path_bytes_size = (appdata_offset + system32_offset) * sizeof(wchar_t);

        memcpy_s(
            &system_path_buffer[system32_offset],
            path_bytes_size,
            SystemProfileAppData_RemainingPath,
            path_bytes_size
        );

        wprintf_s(L"SYSTEM's AppData is here: %s\r\n", system_path_buffer);

        return 0;
    
    return 1;

SYSTEM's AppData is here: C:\WINDOWS\system32\config\systemprofile\AppData

【讨论】:

以上是关于是否有本地化安全的方法来获取 SYSTEM 帐户的 AppData 目录?的主要内容,如果未能解决你的问题,请参考以下文章

使用本地帐户使用安全的 ASP Net 5 web api

是否有一个等效的 REST API 函数来获取 Paypal 帐户的余额,类似于 NVP 获取余额 API? [关闭]

使用 SID 识别本地帐户与域帐户

是否可以使用本地 AD 系统帐户通过身份验证过滤器保护 Web api?

从 SDK 获取 Paypal API 凭证

VBS脚本获取安全标识符SID(Security Identifiers)的方法