服务程序中创建带管理员权限的UI进程问题总结

本文介绍了一种在Windows环境下,从服务进程中启动具有管理员权限的UI进程的方法。通过使用服务进程自身的Token并进行适当的设置,可以实现在session1中启动带有管理员权限的进程。解决了创建的进程访问不到当前用户桌面路径的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果UI进程仅仅是一个普通的进程而不需要申请管理员权限,那问题不大,直接在服务里获取explorer.exe的token或者用WTSGetActiveConsoleSessionId和WTSQueryUserToken,然后用CreateProcessAsUser创建即可,好多参数都可以设置默认,当然前提是要等桌面创建好再获取,因为服务是在桌面创建之前就启动了的,这个要注意。然而管理员权限的进程可是不好启动的,以上方法你将会发现类似740之类的错误码(权限不够),于是网上搜了下发现用服务本身的Token,并做相应的设置就可以做到在session1启动这个带管理员权限的UI进程,当然过程花了不少时间,先是能启动了,但是后面发现访问不了当前用户的桌面等,尤其CFileDialog 一弹出就会报一个错误,最后在同事的提醒下应该是环境变量的问题,瞬间恍然大悟,CreateEnvironmentBlock创建环境变量时必须要用当前桌面进程的token来创建,于是就搞定了访问当前用户桌面路径访问不到的问题,现在还有一个当前用户注册表访问不自然的问题,必须要通过获取当前用户的SID来组合访问注册表HKEY_CURRENT_USER,好了废话少说,虽然现在创建出来的进程用户名仍然是SYSTEM,但是它的访问权限是在管理员之上的,当前用户的东西也可以访问了,在session 1下,只是注册表访问有点不问题,不过可以通过其他方式解决。如果有哪位同仁能够直接创建出具有管理员权限的UI进程,同时创建出来的进程用户名是当前用户烦请告知一声,哈哈,我研究了两天没搞定,放弃了。以下是代码:


#define LOG_BUFFER_SIZE 2048

void PrintfDbgStr( const char * pszformatstring , ... )
{
	char szBuffer[LOG_BUFFER_SIZE]={0};
	va_list		arg_ptr ;
	va_start( arg_ptr, pszformatstring ) ;
	vsprintf(szBuffer, pszformatstring, arg_ptr);
	va_end( arg_ptr ) ;

	OutputDebugStringA(szBuffer);
}

/*
是否已经进入桌面
*/
BOOL IsDesktopVisible()
{

	BOOL  bRet = FALSE;
	HANDLE hProcessSnap = NULL;
	PROCESSENTRY32 pe32 = {0};
	hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE)
		return (FALSE);
	pe32.dwSize = sizeof(PROCESSENTRY32);
	if (Process32First(hProcessSnap, &pe32))
	{
		do
		{
			if(!_tcscmp(_wcsupr(pe32.szExeFile),_T("EXPLORER.EXE")))
			{
				bRet =  TRUE;
				break;
			}
		}while (Process32Next(hProcessSnap, &pe32));
	}

	CloseHandle (hProcessSnap);
	return bRet;
}


下面是启动进程的函数

BOOL  RunExeInSession1(TCHAR* szExeFile)
{
	BOOL  bSuccess = TRUE;

	HANDLE hToken = NULL;
	HANDLE hTokenDup = NULL;
	do 
	{
		if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken))
		{
			if(DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS,NULL, SecurityIdentification, TokenPrimary, &hTokenDup))
			{
				DWORD dwSessionId = WTSGetActiveConsoleSessionId();
				if(!SetTokenInformation(hTokenDup,TokenSessionId,&dwSessionId,sizeof(DWORD)))
				{
					PrintfDbgStr("SetTokenInformation error !error code:%d",GetLastError());
					bSuccess = FALSE;
					break;
				}

				STARTUPINFO si;
				PROCESS_INFORMATION pi;
				ZeroMemory(&si,sizeof(STARTUPINFO));
				ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
				si.cb = sizeof(STARTUPINFO);
				si.lpDesktop = _T("WinSta0\\Default");
				si.wShowWindow = SW_SHOW;
				si.dwFlags     =   STARTF_USESHOWWINDOW /*|STARTF_USESTDHANDLES*/;

				HANDLE hToken;
				LPVOID pEnv = NULL;
				WTSQueryUserToken(dwSessionId, &hToken);
				if(!CreateEnvironmentBlock(&pEnv,hToken,FALSE))
				{
					PrintfDbgStr("CreateEnvironmentBlock error !error code:%d",GetLastError());
					CloseHandle(hToken);
					bSuccess = FALSE;
					break;
				}
				CloseHandle(hToken);

				DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
				if(!CreateProcessAsUser(hTokenDup,NULL,szExeFile,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))
				{
					PrintfDbgStr("CreateProcessAsUser error !error code:%d",GetLastError());
					bSuccess = FALSE;
					break;
				}

				if(pEnv)
				{
					DestroyEnvironmentBlock(pEnv);
				}
			}
			else
			{
				PrintfDbgStr("DuplicateTokenEx error !error code:%d",GetLastError());
				bSuccess = FALSE;
				break;
			}
		}
		else
		{
			PrintfDbgStr("cannot get administror!error code:%d",GetLastError());
			bSuccess = FALSE;
			break;
		}
	}while(0);

	if(hTokenDup != NULL && hTokenDup != INVALID_HANDLE_VALUE)
		CloseHandle(hTokenDup);
	if(hToken != NULL && hToken != INVALID_HANDLE_VALUE)
		CloseHandle(hToken);

	return  bSuccess;
}



参考文章:

  http://blog.youkuaiyun.com/woshinia/article/details/7850295

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值