我有一个程序,直接运行则可以修改桌面,做了一个守护服务(发现进程不在就启动),在服务里面创建进程,这个时候进程是SYSTEM用户.用了CreateProcessAsUser()后,总算是Administrator用户了,可是桌面死活改不了,请大家帮忙!
//下面是服务程序中的代码
HANDLE hExp = GetProcessHandle("EXPLORER.EXE");
if(hExp == NULL)
return FALSE; OpenProcessToken(hExp,TOKEN_ALL_ACCESS,&hToken);
if(hToken == NULL)
return FALSE; ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb        = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default"; TCHAR szParameter[10] = {0}; if(CreateProcessAsUser(hToken,lpAppName,szParameter,NULL,
NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&si,&pi))
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}

解决方案 »

  1.   

    在你那个改桌面的进程里打断点调试啊!
    调用设置桌面的函数后,GetLastError()看下
      

  2.   

    程序没有错,
    原因是服务程序是和登陆用户无关的,先于WinLogon,而桌面是和用户相关的,一个用户对应一个或多个桌面——当然,只有一个是可见的。
    由于修改桌面的程序是被服务程序启动的,因此无法得到用户的信息。
    看了一些牛人说可以用DACL和ACEs来做,可是改过后还是不行。因为我对DACL和ACEs不熟,所以希望能有人指点一下。
      

  3.   

    1 CreateService 时 在dwServiceType加上SERVICE_INTERACTIVE_PROCESS标记.
    2 http://www.osronline.com/showthread.cfm?link=102869
      

  4.   

    我的环境是Windows XP,我是用服务程序创建了一个客户程序,这个客户程序使用了IActiveDesktop来设置桌面.我想知道,客户程序里面要加上一些特别的代码吗?下面是我在创建客户程序的代码 HANDLE              hToken;
    HDESK               hdesk;
    HWINSTA             hwinsta;
    PROCESS_INFORMATION pi;
    PSID                psid;
    STARTUPINFO         si; HANDLE hExp = GetProcessHandle("EXPLORER.EXE");
    if(hExp == NULL)
    return FALSE; OpenProcessToken(hExp,TOKEN_ALL_ACCESS,&hToken);
    if(hToken == NULL)
    return FALSE; HWND hDesk = GetDesktopWindow();
    // BOOL bOk = ImpersonateLoggedOnUser(hToken);
    // GenericLog(Info,"ImpersonateLoggedOnUser %s",bOk?"Ok":"Failed");
    GenericLog(Info,"Desktop HWND %s",(hDesk == GetDesktopWindow())?"Equal":"Not Equal");
    // 
    // obtain a handle to the interactive windowstation
    // 
    hwinsta = OpenWindowStation(
    "winsta0",
    FALSE,
    READ_CONTROL | WRITE_DAC
    );
    if (hwinsta == NULL)
    return RTN_ERROR; HWINSTA hwinstaold = GetProcessWindowStation();
    GenericLog(Info,"WindowStation Old = %.8x,Curr = %.8x",hwinstaold,hwinsta);
    // 
    // set the windowstation to winsta0 so that you obtain the
    // correct default desktop
    // 
    if (!SetProcessWindowStation(hwinsta))
    return RTN_ERROR; // 
    // obtain a handle to the "default" desktop
    // 
    hdesk = OpenDesktop(
    "default",
    0,
    FALSE,
    READ_CONTROL | WRITE_DAC |
    DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS
    );
    if (hdesk == NULL)
    return RTN_ERROR; // 
    // obtain the logon sid of the user fester
    // 
    if (!ObtainSid(hToken, &psid))
    return RTN_ERROR; // 
    // add the user to interactive windowstation
    // 
    if (!AddTheAceWindowStation(hwinsta, psid))
    return RTN_ERROR; // 
    // add user to "default" desktop
    // 
    if (!AddTheAceDesktop(hdesk, psid))
    return RTN_ERROR; // 
    // free the buffer for the logon sid
    // 
    RemoveSid(&psid); // 
    // close the handles to the interactive windowstation and desktop
    // 
    CloseWindowStation(hwinsta); CloseDesktop(hdesk);
    //  ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb        = sizeof(STARTUPINFO);
    si.lpDesktop = "winsta0\\default"; TCHAR szParameter[10] = {0};
    // ShellExecute(NULL,"open",lpAppName,NULL,NULL,SW_HIDE);
    if(CreateProcessAsUser(hToken,lpAppName,szParameter,NULL,
    NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&si,&pi))
    {
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    GenericLog(Info,"Running %s ....",lpAppName);
    UnregisteTimer(TIMER_CONNECT);
    RegisteTimer(TIMER_FEEDDOG,3000);
    return 1;
    }
    else
    {
    GenericLog(Info,"CreateProcess %s Fails ,reason = %d",lpAppName,GetLastError());
    }
    SetProcessWindowStation(hwinstaold); 
    return RTN_OK;
      

  5.   

    我的客户进程里面用的IActiveDesktop来改变桌面,这有关系吗?
      

  6.   

    应该是不用的,不过你还是在IActiveDesktop输出当前的用户名,看看是不是正确。
      

  7.   

    那么我是该用"winsta0\\default"桌面呢?还是用其他的什么桌面呢?
      

  8.   

    按照你所说的,我在客户程序里面调用GetUserName()得到的是当前用户的用户名.我试了一下,如果用服务程序打开客户程序,那么客户程序将不能显示桌面背景,可是如果这时打开IE的属性,点击确定,那么背景就会显示出来.而直接运行客户程序的话,就不会出现问题.
    又,我的服务程序是用OpenProcessToken打开EXPLORER.EXE的令牌.在调用CreateProcessAsUser前调用ImpersonateLoggedOnUser,在调用完CreateProcessAsUser()后调用RevertToSelf().
      

  9.   

    呵呵,问题解决了,在ImpersonateLoggedOnUser之前调用LoadUserProfile(),因为IActiveDesktop在设置桌面的时候会用到一些HKEY_CURRENT_USER键里面的东西,CreateProcessAsUser不负责载入用户配置.新问题又来了
    在XP下测试没问题,怎么在Win2000下又不好使了呢?