Windows交互服务

在Windows中服务与桌面分别位于不同的会话中,服务与桌面交互主要有以下方法:

1.  在用户会话中创建进程,服务与该进程交互,实现服务与桌面交互。这种方法可以实现复杂的交互,但首先需要解决的是获取当前用户的会话,利用CreateProcessAsUser函数来创建进程。

2.  通过函数WTSSendMessage实现弹窗提醒。

这里将展示第一种方法,在创建服务函数CreateService中有三个参数需要注意:

1)      dwServiceType必须含SERVICE_INTERACTIVE_PROCESS选项

2)      lpServiceStartName必须是LocalSystem,默认NULL就可以。

3)      lpPassword为NULL。

获取当前会话主要为通过函数WTSGetActiveConsoleSessionId来获取当前活动会话,然后获取用户Token作为CreateProcessAsUser函数的参数。主要函数代码如下:

dwSessionId = WTSGetActiveConsoleSessionId();
WTSQueryUserToken_t WTSQueryUserTokenProc = (WTSQueryUserToken_t)(::GetProcAddress(hmod,"WTSQueryUserToken"));
// Get token of the logged in user by the active session ID
BOOL bRet = (*WTSQueryUserTokenProc)(dwSessionId, ¤tToken);
if (!bRet)
{
	::FreeLibrary(hmod);
    return 0;
}

    bRet = DuplicateTokenEx(currentToken, //TOKEN_ASSIGN_PRIMARY | SecurityImpersonation
             MAXIMUM_ALLOWED,
             0,SecurityImpersonation , TokenPrimary, &primaryToken);
	 if (!bRet)
    {
		::FreeLibrary(hmod);
        return 0;
    }

	if(!::SetTokenInformation(primaryToken,TokenSessionId,&dwSessionId,sizeof(DWORD)))
	{
		::FreeLibrary(hmod);
        return 0;
	}
	if(!::SetPrivilege(primaryToken,SE_TCB_NAME,TRUE)) {
		::FreeLibrary(hmod);
		return 0;
	}

	::FreeLibrary(hmod);
return primaryToken;
Session解决了,CreateProcessAsUser就可以顺利调用了:

HANDLE primaryToken = ::GetCurrentUserToken();
	if (primaryToken == 0)
	{
		return INVALID_HANDLE_VALUE;
	}

	void* lpEnvironment = NULL; 
	HMODULE hmod = ::LoadLibrary(TEXT("Userenv.dll"));
CreateEnvironmentBlock_t CreateEnvironmentBlockProc = (CreateEnvironmentBlock_t)(::GetProcAddress(hmod,"CreateEnvironmentBlock"));

	// Get all necessary environment variables of logged in user
	// to pass them to the process
	BOOL resultEnv = (*CreateEnvironmentBlockProc)(&lpEnvironment,primaryToken, TRUE);
	if (!resultEnv)
	{ 
		::FreeLibrary(hmod);	
		::CloseHandle(primaryToken);
		::free(primaryToken);
		return INVALID_HANDLE_VALUE;
	}

	DWORD dwSize = ::_tclen(exe) + ::_tclen(argument) + 10;
	dwSize = dwSize * sizeof(TCHAR);
	PWSTR cmd =  new TCHAR[dwSize];
	if(argument != NULL && ::_tclen(argument) != 0) 
		::StringCchPrintfW(cmd,dwSize,TEXT("\"%s\" %s"),exe,argument);
	else
		::StringCchPrintfW(cmd,dwSize,TEXT("%s"),exe);

	PROCESS_INFORMATION processInfo;
	STARTUPINFO StartupInfo = {sizeof(StartupInfo)};
	SECURITY_ATTRIBUTES Security1;
	SECURITY_ATTRIBUTES Security2;
	
	ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
	StartupInfo.cb = sizeof(STARTUPINFO);
	StartupInfo.lpDesktop = L"winsta0\\default";

	// Start the process on behalf of the current user 
	// error in here,maybe should elevate the service permission
	BOOL result = CreateProcessAsUser(primaryToken,  
		cmd,NULL,NULL, 
		NULL,/*&Security1,&Security2*/ FALSE, /*CREATE_NO_WINDOW |*/ NORMAL_PRIORITY_CLASS | 
		CREATE_UNICODE_ENVIRONMENT, lpEnvironment, path, 
		&StartupInfo, &processInfo);

	if(!result) {
		::FreeLibrary(hmod);
		::CloseHandle(primaryToken);
		delete cmd;
		return INVALID_HANDLE_VALUE;
	}

	DestroyEnvironmentBlock_t DestroyEnvironmentBlockProc = (DestroyEnvironmentBlock_t)(::GetProcAddress(hmod,"DestroyEnvironmentBlock"));
	(*DestroyEnvironmentBlockProc)(lpEnvironment);
	::FreeLibrary(hmod);

	::FreeLibrary(hmod);
	::CloseHandle(primaryToken);
	delete cmd;
	return processInfo.hProcess;

完整源码见这里

MSDN交互服务: https://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值