本帖最后由 VisualEleven 于 2014-08-20 18:00:26 编辑

解决方案 »

  1.   

    有UAC,你启动的时候,是普通用户权限,你是否有Administrator的用户名和密码
      

  2.   

    调用ShellExecuteEx试试,传入runas参数
      

  3.   

    win8分为desktop和metro程序,desktop下的程序和之前windows版本没有什么区别。并且在desktop下写的服务是可以启动exe程序的,只不过service的权限太高是属于section0级别,而exe是属于用户级别。所以想在service下启动exe,需要做三件事:1、事先模拟用户权限;2、启动exe,用shell方法之类的;3、把权限修改回来。我能说出这几个点的原因是我之前也做过同样的问题,并且是可行的。不过现在手头没有模拟用户权限的代码,楼主要是急可以上百度上查一下模拟权限之类的。要是不急,明天我可以把代码献上。(只要我回家能想起来这事:) )至于metro程序,我可以很负责的告诉你,service无法启动metro。我们项目团队做了近,3年多的metro了我还没有听说过有人说service可以调用metro下的app之类的说法。不要和我说metro才出来没两年,我们在metro没上市时就已经开始开发了。
      

  4.   

    class WTSSessionHolder
    {
    DWORD nCount;
    WTS_SESSION_INFO* pSessions; WTSSessionHolder( const WTSSessionHolder& );
    WTSSessionHolder& operator=( const WTSSessionHolder& );public:
    WTSSessionHolder()
    : nCount(0), pSessions( NULL )
    {
    if ( !::WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessions, &nCount ) )
    {
    AtlThrowLastWin32();
    }
    } ~WTSSessionHolder()
    {
    ::WTSFreeMemory( pSessions );
    } typedef const WTS_SESSION_INFO* const_iterator; const WTS_SESSION_INFO* begin() const
    {
    return pSessions;
    } const WTS_SESSION_INFO* end() const
    {
    return pSessions + nCount;
    }
    };class WTSUserHolder
    {
    CHandle hUserToken;
    BOOL bImpersonated; WTSUserHolder( const WTSUserHolder& );
    WTSUserHolder& operator=( const WTSUserHolder& ); static inline HANDLE GetSessionUserToken()
    {
    DWORD dwSessionID = ::WTSGetActiveConsoleSessionId();
    if ( dwSessionID != 0xFFFFFFFF )
    {
    CHandle hUserToken;
    if ( ::WTSQueryUserToken( dwSessionID, &hUserToken.m_h ) )
    {
    return hUserToken.Detach();
    }
    }
    WTSSessionHolder sessions;
    WTSSessionHolder::const_iterator end = sessions.end();
    for( WTSSessionHolder::const_iterator i = sessions.begin() ; i != end ; ++i )
    {
    CHandle hUserToken;
    if ( ::WTSQueryUserToken( i->SessionId, &hUserToken.m_h ) )
    {
    return hUserToken.Detach();
    }
    }
    return NULL;
    }public:
    WTSUserHolder()
    : hUserToken(), bImpersonated( FALSE )
    {
    } ~WTSUserHolder()
    {
    UnImpersonate();
    } BOOL AttachCurrentUser()
    {
    CHandle hUserToken( GetSessionUserToken() );
    hUserToken = hUserToken;
    return hUserToken ? TRUE : FALSE;
    } HANDLE GetUserToken() const
    {
    return hUserToken;
    } BOOL Impersonate()
    {
    if ( !bImpersonated )
    {
    bImpersonated = ::ImpersonateLoggedOnUser( hUserToken );
    }
    return bImpersonated;
    } void UnImpersonate()
    {
    if ( bImpersonated && ::RevertToSelf() )
    {
    bImpersonated = FALSE;
    }
    } BOOL IsImpersonated() const
    {
    return bImpersonated;
    }
    };代码献上,这个是5年前写的二个类,基本上就是遍历所有用户,最后模拟成用户的权限。要解决的问题就是由于我在服务程序中想做一些用户权限下需要做的事。和楼主想的是一类问题,启动exe在服务在用服务权限是不行的,先模拟成用户权限,启动,启动完之后再模拟回来。下面是模拟的代码。WTSUserHolder objUser;
    if ( objUser.AttachCurrentUser() )
    {
        objUser.Impersonate();//这个就是模拟,在这之后就可以启动你的exe程序了。
    }
    因为我做的是一个类,在对象objUser析构时就会自动改为secion0权限。对了,关于里面用到的api楼主自己查一下msdn看看需要包含什么头文件和库,否则编译不过的哦。
      

  5.   

    谢谢大家的热心回复,特别谢谢SiGoYi,小弟我弄了快一个月了,郁闷,一直在MSDN上找sample,demo,但是一直没有解决,由于对win8系统开发不熟悉,所以这个问题无法解决,除了win8其他的系统都是可以的。
    我今天来试试,谢谢大家,
      

  6.   

    为什么服务不可以打开 metro 呢?
    至少可以使用 命令行打开 metro .
    我没有试过服务打开 metro app ,但是我认为至少可以创建一个 desktop 来打开 metro app.谢谢你的 代码,我收藏了。
      

  7.   

    使用了SiGoYi的方法测试了,在win8下虽然可以启动线程,但是B程序没有启动UI,只是任务管理器中有这个进程,而且这个进程是SYSTEM权限。
    现在要求是,在win8下,必须要B程序UI正常启动,而且是当前的用户权限,不是SYSTEM权限。我之前自己写的代码
    int win_impersonate_desktop_user() 
    {
    HANDLE desktopUserHandle = NULL;
    TCHAR szMyUsername[1024];
    DWORD usize = 1024; if (active_token != NULL)
    {
    BMLOG(_T("IMPERSONATE_HANDLE_IN_USE")); CloseHandle(active_token);
    active_token = NULL; return IMPERSONATE_HANDLE_IN_USE;
    }  if(!EnableDebugPriv())
      {
      //printf("You probably don't have the SE_DEBUG_NAME privilege\n");
      BMLOG(_T("You probably don't have the SE_DEBUG_NAME privilege"));
      return IMPERSONATE_PRIVILEDGE_FAILURE;
      } if (WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &desktopUserHandle) == FALSE)
    {
    //debug_printf(DEBUG_NORMAL,
    // "Error getting desktop user token.  (Error : %d)\n",
    // GetLastError());
    BMLOG(_T("Error getting desktop user token.  (Error : %d)"),GetLastError());
    return IMPERSONATE_BAD_USER_TOKEN;
    } if (DuplicateTokenEx(desktopUserHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation,
    TokenImpersonation, &active_token) == FALSE)
    {
    CloseHandle(desktopUserHandle); // Clean it up.
    //debug_printf(DEBUG_NORMAL,
    // "Error duplicating desktop user token.  (Error : %d)\n",
    // GetLastError());
    BMLOG(_T("Error duplicating desktop user token.  (Error : %d)"),GetLastError());
    return IMPERSONATE_BAD_USER_TOKEN;
    } CloseHandle(desktopUserHandle); // We are done with it.  We made a dup.
    if (ImpersonateLoggedOnUser(active_token) == FALSE)
    {
    //debug_printf(DEBUG_NORMAL,
    // "Couldn't impersonate logged on user. (Error : %d)\n",
    // GetLastError());
    CloseHandle(active_token);
    active_token = NULL;
    BMLOG(_T("Couldn't impersonate logged on user. (Error : %d)"),GetLastError());
    return IMPERSONATE_FAILURE;
    } if (GetUserName(szMyUsername, &usize) != 0)
    {
    //debug_printf(DEBUG_CONTEXT, "Impersonating user: %s!\n",
    // szMyUsername);
    BMLOG(_T("Impersonating user: %s"),szMyUsername);
    } return IMPERSONATE_NO_ERROR;
    }
    BOOL EnableDebugPriv(void)
    {
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;
     HANDLE hProcess;  DWORD dwPID;
     dwPID = GetCurrentProcessId();   if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) == NULL) 
      {
      BMLOG(_T("hProcess = OpenProcess(PROCESS_ALL_ACCESS %d"),GetLastError());
      return FALSE;
      } tp.PrivilegeCount           = 1;
    //tp.Privileges[0].Luid       = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!OpenProcessToken(
    GetCurrentProcess(),
     TOKEN_ADJUST_DEFAULT|TOKEN_ADJUST_SESSIONID /*| TOKEN_ALL_ACCESS*//*MAXIMUM_ALLOWED | READ_CONTROL|WRITE_DAC*//*|TOKEN_READ|TOKEN_WRITE*/|TOKEN_QUERY,
    &hToken ))
    {
    //PERR("OpenProcessToken");

    BMLOG(_T("OpenProcessToken=%d"),GetLastError());
    return(FALSE);
    } if(!LookupPrivilegeValue(NULL, /*SE_DEBUG_NAME*/SE_TCB_NAME , /*&luid*/&tp.Privileges[0].Luid))
    {
    //PERR("LookupPrivilegeValue");

    BMLOG(_T("LookupPrivilegeValue=%d"),GetLastError());
    CloseHandle(hToken);
    return(FALSE);
    }//  tp.PrivilegeCount           = 1;
    //  tp.Privileges[0].Luid       = luid;
    //  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if(!AdjustTokenPrivileges(
    hToken,
    FALSE,
    &tp,
    sizeof(TOKEN_PRIVILEGES),
    NULL,
    NULL ))
    {

    BMLOG(_T("AdjustTokenPrivileges=%d"),GetLastError());
    //PERR("AdjustTokenPrivileges");
    CloseHandle(hToken);
    return(FALSE);
    } CloseHandle(hToken); return(TRUE);}如果把我的这段代码加上,win8下进程B不能启动,打印log是AdjustTokenPrivileges=5,然后我就一直解决不了了。
      

  8.   

    @SiGoYi
    老大,在么? 麻烦给指导一下
      

  9.   

    可以用CreateProcessAsUser,另外,确实得关注一下权限的问题。