我的应用程序作为服务运行,在某些时候它需要循环遍历系统上的所有现有用户帐户(我认为这可以通过NetUserEnum()
完成)并尝试访问每个找到的用户下的某个文件%APPDATA%路径。问题是我不知道如何获得该用户特定的路径(%APPDATA%)。
由于应用程序作为服务(SYSTEM)运行,因此我无法使用环境或SHGetFolderPath()
。最初我以为我可以使用LogonUser()
但它总是向我抛出错误1326,无论我在用户,管理员还是SYSTEM下运行我的应用程序测试代码。 (winxp作为测试平台)。如果有办法获取用户登录句柄,我可以在SHGetFolderPath()
或ExpandEnvironmentStringsForUser()
API中使用它,这是正确的吗?
所以,到目前为止,我尝试使用LogonUser()的代码是关于以下内容(是的,用户名是正确的):
LogonUser(
pw->usri1_name,
L".",
NULL,
LOGON32_LOGON_BATCH,
LOGON32_PROVIDER_DEFAULT,
&authtoken
)
它可能需要我的密码,但我无法在客户机器上知道这一点。我通过快速搜索找到的所有API都依赖于来自LogonUser()的HANDLE,我显然不能拥有......
欢迎任何非棘手和棘手的想法!
答案 0 :(得分:0)
到目前为止的解决方案和结论。
您无法正确使用LogonUser()
。
相反,您的选项来自强制用户homedir之后的路径(您仍然通过任何首选方法获得,我的建议为NetUserEnum()
),基于以下之一: / p>
SHGetFolderPath(CSIDL_APPDATA)
HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
如果您知道任何其他方法,请发表评论。
答案 1 :(得分:0)
服务或应用程序作为“本地系统”运行以获取特殊文件夹
这个例子我们得到 CSIDL_DESKTOPDIRECTORY ,在xp,win7(32,64)上运行良好
DWORD ServiceGetDesktopDirectory(LPWSTR lpUserName, LPWSTR lpPassword,
LPWSTR lpDomain, LPWSTR lpBuffer)
{
HANDLE hToken;
BOOL bRet;
bRet = LogonUserW(lpUserName,
lpDomain,
lpPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken);
if (!bRet) {
error("LogonUser failed, gle = %lu", GetLastError());
return FILE_ERR_INVALID_USERNAME_OR_PASSWORD;
}
NET_API_STATUS ntStatus;
USER_INFO_4 *pUserInfo;
ntStatus = NetUserGetInfo((LPCWSTR)lpDomain,
(LPCWSTR)lpUserName,
4,
(BYTE**)&pUserInfo);
if (ntStatus != NERR_Success) {
error("NetUserGetInfo failed, ntStatus 0X%x", ntStatus);
CloseHandle(hToken);
return FILE_ERR_SYSTEM_ERROR;
}
PROFILEINFOW profile;
memset(&profile, 0, sizeof(PROFILEINFOW));
profile.dwSize = sizeof(PROFILEINFOW);
profile.lpUserName = lpUserName;
profile.lpProfilePath = pUserInfo->usri4_profile;
bRet = LoadUserProfileW(hToken, &profile);
if (!bRet) {
error("LoadUserProfile failed, gle = %lu", GetLastError());
CloseHandle(hToken);
NetApiBufferFree(pUserInfo);
return FILE_ERR_SYSTEM_ERROR;
}
HRESULT hr;
hr = SHGetFolderPathW(NULL,
CSIDL_DESKTOPDIRECTORY|CSIDL_FLAG_CREATE,
hToken,
0,
lpBuffer);
if (FAILED(hr)) {
error("SHGetFolderPath failed, hr 0X%x", hr);
NetApiBufferFree(pUserInfo);
UnloadUserProfile(hToken, profile.hProfile);
CloseHandle(hToken);
return FILE_ERR_SYSTEM_ERROR;
}
NetApiBufferFree(pUserInfo);
UnloadUserProfile(hToken, profile.hProfile);
CloseHandle(hToken);
return FILE_ERR_OK;
}
答案 2 :(得分:-1)
您可以使用WTSEnumerateSessions()
和WTSQueryUserToken()
来检索每个登录会话的令牌。
另请查看LoadUserProfile()
,这是服务访问特定用户的HKEY_CURRENT_USER
密钥所必需的。用户必须以交互方式或可编程方式登录,或者模拟以获取所需的用户令牌。
另一个选项是枚举HKEY_USERS
密钥以检索用户帐户的SID,然后使用LookupAccountSid()
检索其用户名,然后根据操作系统版本手动格式化AppData路径。不那么灵活,但不太依赖于特定于用户的注册数据。
否则,忘记尝试从服务写入特定于用户的文件夹。请改为使用常见的共享文件夹,例如CSIDL_COMMON_APPDATA
和FOLDERID_ProgramData
。