窗口服务应该与UI交互

时间:2011-10-24 17:16:49

标签: windows-services

我有一个Windows服务,它在Win 2003 OS上启动时启动GUI。但是由于win 2008(Session 0 Isolation)中引入的安全功能,我的窗口服务无法启动GUI。如何在win 2008平台上通过窗口服务启动GUI。

注意:我不想启用“交互式服务检测”来实现解决方案。 如果有人遇到或实施了上述问题,请告诉我。

我已经创建了示例服务,我将下面的代码放在OnStart函数中。 嗨Seva,我完成了你的评论并制作了一个示例Windows服务。我在OnStart下面放下代码。服务正在启动但它没有显示“notepad.exe”。你能说明我在这里做错了吗?

HANDLE hToken    = NULL;
HANDLE hTokenDup = NULL;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof( STARTUPINFO ) );
ZeroMemory( &pi, sizeof( PROCESS_INFORMATION ) );

si.cb = sizeof( STARTUPINFO );
si.lpDesktop = _T("Winsta0\\Default");

DWORD  dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID pEnvironment = NULL;
LPFNCREATEENVIRONMENTBLOCK  lpfnCreateEnvironmentBlock  = NULL;
LPFNDESTROYENVIRONMENTBLOCK lpfnDestroyEnvironmentBlock = NULL;
HMODULE hUserEnvLib = NULL;
hUserEnvLib = LoadLibrary( _T("userenv.dll") );
if ( NULL != hUserEnvLib ) {
    lpfnCreateEnvironmentBlock  = (LPFNCREATEENVIRONMENTBLOCK)
    GetProcAddress( hUserEnvLib, "CreateEnvironmentBlock" );

    lpfnDestroyEnvironmentBlock = (LPFNDESTROYENVIRONMENTBLOCK)
    GetProcAddress( hUserEnvLib, "DestroyEnvironmentBlock" );
}
OpenThreadToken( GetCurrentThread(), TOKEN_DUPLICATE, TRUE, &hToken );
DuplicateTokenEx( hToken,
                  TOKEN_IMPERSONATE|TOKEN_READ|TOKEN_ASSIGN_PRIMARY|TOKEN_DUPLICATE,
                  NULL, SecurityImpersonation, TokenPrimary, &hTokenDup );
RevertToSelf( );
CloseHandle( hToken );
if ( NULL != lpfnCreateEnvironmentBlock ) {
    if ( lpfnCreateEnvironmentBlock( &pEnvironment, hTokenDup, FALSE ) ) {
        dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;   // must specify
    }
    else {
        pEnvironment = NULL;
        OutputDebugString( _T(" CreateEnvironmentBlock() -- FAILED") );
    }
}
else {
    OutputDebugString(_T(" FAILED - GetProcAddress(CreateEnvironmentBlock)"));
}
CreateProcessAsUser( hTokenDup, NULL, _T("C:\\windows\\system32\\notepad.exe"),
                     NULL, NULL, FALSE, dwCreationFlag,
                     pEnvironment, NULL, &si, &pi );
if ( NULL != lpfnDestroyEnvironmentBlock )
    lpfnDestroyEnvironmentBlock( pEnvironment );
if ( NULL != hUserEnvLib ) FreeLibrary( hUserEnvLib );
CloseHandle( hTokenDup );

以上代码似乎不起作用,任何人都可以帮我解决这个问题? -dev

1 个答案:

答案 0 :(得分:0)

MSDN中描述了处理会话隔离的推荐方法。您有两种选择:

  1. 一种简单但非常有限的方法是使用WTSSendMessage API在用户会话中显示对话框。
  2. 更难,但更灵活的选项是在用户会话中运行(并附加到用户桌面)的单独进程。您的服务使用某种IPC机制与该进程通信。
  3. 对于#2,几乎没有方法可以在用户会话中启动进程。一种流行的方法是挂钩At Logon触发器。另一种方法是使用CreateProcessAsUser。您可以查找示例代码,以便使用它在不同的会话here中启动进程。