以服务权限,即SYSTEM帐户启动的程序是无法取得用户的profile的,比如startup文件夹的路径。
首先,Shell函数是不行的:
SHGetSpecialFolderPath取得的是C:\Windows\system32\config\systemprofile\
其次,环境变量也得不到。
GetEnvironmentVariable返回203( ERROR_ENVVAR_NOT_FOUND)
注:从服务应用程序可以拿到全局的环境变量,诸如ALLUSERS等等,但是各个用户的就搞不定了。
虽说从服务来访问用户的profile是一种非常不好的设计,但是如果有一些特殊需求的话,,
可以使用下面的方法。
BOOL bRes = FALSE;char lpPath[MAX_PATH];
DWORD RetVal = 0;
DWORD ErrCode = 0;
DWORD ConsoleSessionId = 0;
// 函数的句柄
HMODULE hInstKernel32 = NULL;
HMODULE hInstWtsapi32 = NULL;
// Token的句柄
HANDLE hTokenUser = NULL;
HANDLE hTokenThisProcess = NULL;
HANDLE hTokenThis = NULL;
// WTSGetActiveConsoleSessionId 函数,得到当前登录用户的会话ID
// 这里的代码用的是VC6,新版的SDK已经包括此函数,无需LoadLibrary了。
typedef DWORD (WINAPI *WTSGetActiveConsoleSessionIdPROC)();
WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
hInstKernel32 = LoadLibrary("Kernel32.dll");
if (!hInstKernel32)
{
return FALSE;
}
WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC)GetProcAddress(hInstKernel32,"WTSGetActiveConsoleSessionId");
if (!WTSGetActiveConsoleSessionId)
{
return FALSE;
}
// WTSQueryUserToken 函数,通过会话ID得到令牌
typedef BOOL (WINAPI *WTSQueryUserTokenPROC)(ULONG SessionId, PHANDLE phToken );
WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
hInstWtsapi32 = LoadLibrary("Wtsapi32.dll");
if (!hInstWtsapi32)
{
return FALSE;
}
WTSQueryUserToken = (WTSQueryUserTokenPROC)GetProcAddress(hInstWtsapi32,"WTSQueryUserToken");
if (!WTSQueryUserToken)
{
return FALSE;
}
// 得到当前激活用户的会话ID
ConsoleSessionId = WTSGetActiveConsoleSessionId();
// 得到当前登录用户的令牌
bRes = WTSQueryUserToken( ConsoleSessionId, &hTokenUser);
if (!bRes)
{
return FALSE;
}
// 模仿成当前登录用户
bRes = ImpersonateLoggedOnUser(hTokenUser);
if (!bRes)
{
return FALSE;
}
// 取得当前用户的Startup文件夹路径
bRes = SHGetSpecialFolderPath(NULL,lpPath,CSIDL_STARTUP,TRUE);//CSIDL_STARTUP 表示的是开始菜单
if (!bRes)
{
return FALSE;
}
else
{
MessageBox(NULL,lpPath,"Startup",MB_OK);
}
// 终止模拟,返回
RevertToSelf();