Win7 里后台服务使用 CreateProcessAsUser 函数启动程序后,被启动的程序不能执行 ShellExecute 函数(参数正确,返回值正常,但没有结果),请问各位大神是怎么解决的?

解决方案 »

  1.   

    启动代码:DWORD _stdcall LaunchAppIntoDifferentSession( LPTSTR lpCommand, LPTSTR lpWorkDir)
    {
    DWORD dwRet = 0;
    PROCESS_INFORMATION pi ;
    STARTUPINFO si ;
    DWORD dwSessionId ;
    HANDLE hUserToken = NULL;
    HANDLE hUserTokenDup = NULL;
    HANDLE hPToken = NULL;
    HANDLE hProcess = NULL;
    DWORD dwCreationFlags ; HMODULE hInstKernel32 = NULL;
    typedef DWORD (WINAPI * WTSGetActiveConsoleSessionIdPROC)();
    WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL; hInstKernel32 = LoadLibrary ("Kernel32.dll" ); if (!hInstKernel32 )
    {
    return FALSE ;
    } OutputDebugString("LaunchAppIntoDifferentSession 1\n" );
    WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC )GetProcAddress( hInstKernel32,"WTSGetActiveConsoleSessionId" );
    // Log the client on to the local computer.
    dwSessionId = WTSGetActiveConsoleSessionId (); do
    {
    WTSQueryUserToken( dwSessionId ,&hUserToken );
    dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
    ZeroMemory( &si , sizeof( STARTUPINFO ) );
    si.cb = sizeof( STARTUPINFO );
    si.lpDesktop = "winsta0\\default" ;
    ZeroMemory( &pi , sizeof( pi) );
    TOKEN_PRIVILEGES tp ;
    LUID luid ; if( !::OpenProcessToken ( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
    | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
    | TOKEN_READ | TOKEN_WRITE , &hPToken ) )
    {
    dwRet = GetLastError ();
    break;
    }
    else; if ( !LookupPrivilegeValue ( NULL, SE_DEBUG_NAME, &luid ) )
    {
    dwRet = GetLastError ();
    break;
    }
    else;
    tp.PrivilegeCount =1;
    tp.Privileges [0].Luid = luid;
    tp.Privileges [0].Attributes = SE_PRIVILEGE_ENABLED; if( !DuplicateTokenEx ( hPToken, MAXIMUM_ALLOWED, NULL , SecurityIdentification , TokenPrimary, & hUserTokenDup ) )
    {
    dwRet = GetLastError ();
    break;
    }
    else; //Adjust Token privilege
    SetTokenInformation ( hUserTokenDup,TokenSessionId ,(void*)& dwSessionId,sizeof (DWORD) ); if( !AdjustTokenPrivileges ( hUserTokenDup, FALSE, &tp , sizeof(TOKEN_PRIVILEGES ), (PTOKEN_PRIVILEGES) NULL, NULL ) )
    {
    dwRet = GetLastError ();
    break;
    }
    else; LPVOID pEnv =NULL;
    if( CreateEnvironmentBlock ( &pEnv, hUserTokenDup, TRUE ) )
    {
    dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT ;
    }
    else pEnv =NULL; // Launch the process in the client's logon session.
    if( CreateProcessAsUser ( hUserTokenDup, // client's access token
    NULL, // file to execute
    lpCommand, // command line
    NULL, // pointer to process SECURITY_ATTRIBUTES
    NULL, // pointer to thread SECURITY_ATTRIBUTES
    TRUE, // handles are not inheritable
    dwCreationFlags,// creation flags
    pEnv, // pointer to new environment block
    lpWorkDir, // name of current directory
    & si, // pointer to STARTUPINFO structure
    & pi // receives information about new process
    ) )
    {
    }
    else
    {
    dwRet = GetLastError ();
    break;
    }
    }
    while( 0 ); //Perform All the Close Handles task
    if( NULL != hUserToken )
    {
    CloseHandle( hUserToken );
    }
    else; if( NULL != hUserTokenDup)
    {
    CloseHandle( hUserTokenDup );
    }
    else; if( NULL != hPToken )
    {
    CloseHandle( hPToken );
    }
    else; return dwRet ;
    }
      

  2.   

    被启动的程序不能执行 ShellExecute 函数,参数正确,返回值正常,但没有结果。被启动的程序现在也没法改成别的方法,因为内部使用了很多类似的方法,一些还是Microsoft以前提供的其他库,用到了类似的方法,根本改不了。
      

  3.   

    是否拿到了explorer的token,然后再CreateProcessAsUser
      

  4.   

    @oyljerry 版主,怎样拿?目前是模拟桌面winsta0\\default的方式,这是从网上找的一个方法,以前自己写的一个方法,在Win7之前的系统上采用复制 Explorer.exe 进程的令牌的方法启动新进程,在Win7及之后的系统上采用复制 WINLOGON.exe 进程的令牌的方法启动新进程,但在Win7上新启动的进程存在上述问题,如是改成了现在网上找的这种方法,发现网上找的这种方法也一样存在这个问题,不知如何解决。
      

  5.   

    令牌许可全部加了,还是不行: EnablePrivilege(hUserTokenDup,SE_CREATE_TOKEN_NAME);
    EnablePrivilege(hUserTokenDup,SE_ASSIGNPRIMARYTOKEN_NAME);
    EnablePrivilege(hUserTokenDup,SE_LOCK_MEMORY_NAME);
    EnablePrivilege(hUserTokenDup,SE_INCREASE_QUOTA_NAME);
    EnablePrivilege(hUserTokenDup,SE_UNSOLICITED_INPUT_NAME);
    EnablePrivilege(hUserTokenDup,SE_MACHINE_ACCOUNT_NAME);
    EnablePrivilege(hUserTokenDup,SE_TCB_NAME);
    EnablePrivilege(hUserTokenDup,SE_SECURITY_NAME);
    EnablePrivilege(hUserTokenDup,SE_TAKE_OWNERSHIP_NAME);
    EnablePrivilege(hUserTokenDup,SE_LOAD_DRIVER_NAME); EnablePrivilege(hUserTokenDup,SE_SYSTEM_PROFILE_NAME);
    EnablePrivilege(hUserTokenDup,SE_SYSTEMTIME_NAME);
    EnablePrivilege(hUserTokenDup,SE_PROF_SINGLE_PROCESS_NAME);
    EnablePrivilege(hUserTokenDup,SE_INC_BASE_PRIORITY_NAME);
    EnablePrivilege(hUserTokenDup,SE_CREATE_PAGEFILE_NAME);
    EnablePrivilege(hUserTokenDup,SE_CREATE_PERMANENT_NAME);
    EnablePrivilege(hUserTokenDup,SE_BACKUP_NAME);
    EnablePrivilege(hUserTokenDup,SE_RESTORE_NAME);
    EnablePrivilege(hUserTokenDup,SE_SHUTDOWN_NAME);
    EnablePrivilege(hUserTokenDup,SE_DEBUG_NAME); EnablePrivilege(hUserTokenDup,SE_AUDIT_NAME);
    EnablePrivilege(hUserTokenDup,SE_SYSTEM_ENVIRONMENT_NAME);
    EnablePrivilege(hUserTokenDup,SE_CHANGE_NOTIFY_NAME);
    EnablePrivilege(hUserTokenDup,SE_REMOTE_SHUTDOWN_NAME);
    EnablePrivilege(hUserTokenDup,SE_UNDOCK_NAME);
    EnablePrivilege(hUserTokenDup,SE_SYNC_AGENT_NAME);
    EnablePrivilege(hUserTokenDup,SE_ENABLE_DELEGATION_NAME);
    EnablePrivilege(hUserTokenDup,SE_MANAGE_VOLUME_NAME);
    EnablePrivilege(hUserTokenDup,SE_IMPERSONATE_NAME);
    EnablePrivilege(hUserTokenDup,SE_CREATE_GLOBAL_NAME); EnablePrivilege(hUserTokenDup,SE_TRUSTED_CREDMAN_ACCESS_NAME);
    EnablePrivilege(hUserTokenDup,SE_RELABEL_NAME);
    EnablePrivilege(hUserTokenDup,SE_INC_WORKING_SET_NAME);
    EnablePrivilege(hUserTokenDup,SE_TIME_ZONE_NAME);
    EnablePrivilege(hUserTokenDup,SE_CREATE_SYMBOLIC_LINK_NAME);35个许可基本都是成功的BOOL EnablePrivilege(HANDLE hToken, LPCTSTR lpszPrivilegeName)
    {
        TOKEN_PRIVILEGES tkp = {0};
        BOOL bRet = LookupPrivilegeValue( NULL, lpszPrivilegeName, &tkp.Privileges[0].Luid );
        if(!bRet) return FALSE;    tkp.PrivilegeCount = 1;
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        bRet = AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL );    return bRet;
    }
    被启动的进程里的 ShellExecute 不能执行是环境块的问题吗? ShellExecute里的参数给的是全路径,参数本身不依赖环境块
      

  6.   

    HINSTANCE res = ShellExecute(m_hWnd,"open","e:\\a.chm",NULL,"e:\\",SW_SHOWMAXIMIZED); 
      

  7.   

    是的,后台服务启动前台与用户交互的程序,这个没问题,就是某些早期类似自动化的东西运行没有结果,比如HINSTANCE res = ShellExecute(m_hWnd,"open","e:\\a.chm",NULL,"e:\\",SW_SHOWMAXIMIZED);返回值是成功的,但帮助文件a.chm并不会打开,还有比这个更重要的,也没法改的东西也不能运行
      

  8.   

    你猜可能是启动成功了,只是在不同的session或者winsta或者desktop。
      

  9.   

    你可以尝试一下:
    在服务中CreateProcessAsUser 启动过一个win32 console application,然后再console application中启动你的GUI窗口程序。
      

  10.   

    1、采用傀儡进程的方法昨天试过,结果一样,解决不了问题2、是否为已启动这个也试过,例子中是打开帮助文件,对于帮助文件,微软使用 hh.exe 打开,打开后 hh.exe 会在运行,取得 hh.exe 控制权后也不可以将 hh.exe删除,关闭了帮助文件则可将 hh.exe 删除服务启动这个程序后,此程序运行了 ShellExecute 去打开帮助文件,没有效果,而且 hh.exe 可以删除,说明ShellExecute是真的没有执行成功所以问题不再这些地方
      

  11.   

    需要事先在a.chm文件上点鼠标右键、安全、信任啥的记不太清了。