📄 服务程序如何获取映射驱动器名.txt
字号:
服务程序如何获取映射驱动器名?
(原创)
writed by xubing in 2005.12.16
本人是在写一个服务程序时遇到了无法获取映射驱动器的问题,通过解决该问题有一些体会,小结如下:
1.CreateService中最后两个参数如果传递NULL,则以系统帐号运行。
“如果一个进程正在一个用户帐号下执行,那么这个进程就同时拥有这个用户所能拥有的一切访问权限,不论是在本机还是网络。系统帐号则是一个特殊的账号,它用来标识系统本身,而且运行在这个帐号下的任何进程都拥有系统上的所有访问权限,但是系统帐号不能在域上使用,无法访问网络资源…
服务也是Win32可执行程序,它也需要执行在一个context,通常服务都是在系统账号下运行,但是也可以根据情况选择让它运行在一个用户账号下,也就会因此获得相应的访问资源的权限。”
--摘自《Windows服务编写原理及探讨》
修改成相应用户即可:
示例:(只说明CreateService最后两个参数)
本机 - _T(".\\user1"), _T("123456")
域(域名为abc.local) - _T("abc.local\\user2"), _T("123456")
2.可以用ChangeServiceConfig2动态修改服务的帐号
3.但是有一个问题,实际中我设置了正确的用户,但只能在安装或启动服务时能够访问
映射驱动器,运行时无法访问。原因是运行时服务是以另一个线程运行的,需要设置该线程的
权限。可以调用ImpersonateLoggedOnUser,该函数需要传递用户的令牌,至于如何得到当前
用户的令牌,则是另一个问题了,可以参考msdn.这里给出一个不需要用户输入而直接获取
explorer.exe的用户令牌的函数,也是从网上找来的,至于如何得到explorer.exe的进程ID
就不用我说了吧。该方法的缺点是必须当前机器中有explorer.exe。
//得到当前登录用户的Token
HANDLE GetCurUserToken()
{
HANDLE hProc = NULL;
HANDLE hToken = NULL;
//通过得到explorer.exe的Token间接得到当前用户的Token
DWORD dwID = GetProcessID(_T("explorer.exe")) ;
if (dwID != -1)
{
hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwID);
if (hProc != NULL)
{
//dwDesiredAccess不设为TOKEN_ALL_ACCESS是为了更准确的确定OpenProcessToken失败的原因
DWORD dwDesiredAccess = TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE;
BOOL bRet = OpenProcessToken(hProc, dwDesiredAccess, &hToken);//TOKEN_ALL_ACCESS
::CloseHandle(hProc);
if (bRet)
{
return hToken ;//成功
}
else
WriteDebug("CUSPServerMonitor - Open process token of explorer.exe failed") ;
}
else
WriteDebug("CUSPServerMonitor - Open process of explorer.exe failed") ;
}
else
{
WriteDebug("CUSPServerMonitor - Get process id of explorer.exe is -1") ;
}
return NULL ;
}
4.如何使用ImpersonateLoggedOnUser呢,以下仅供参考。
在服务运行的函数中这样写:
// 启动服务时被系统调用
void CTestService::Run(DWORD dwArgc, LPTSTR * ppszArgv)
{
ReportStatus(SERVICE_START_PENDING);
//...
// TODO: 在此添加您的专用代码
HANDLE hToken = GetCurUserToken() ;//得到当前用户的令牌
if (::ImpersonateLoggedOnUser(hToken))//让当前线程模拟该用户的security-context
{
WriteDebug("CTestService::Run() - ImpersonateLoggedOnUser ok");
}
else
{
WriteDebug("CTestService::Run() - ImpersonateLoggedOnUser failed - %s", GetLastErrorText());
}
//...
// report SERVICE_RUNNING immediately before you enter the main-loop
// DON'T FORGET THIS!
ReportStatus(SERVICE_RUNNING);
//...
}
欢迎交流!
email: xubing728@yahoo.com.cn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -