我的一个应用程序调试过程中与编译后均运行正常,但由于特殊原因,这个程序必须由一个系统服务来调用(shell "我的程序"),此时在任务管理器中可以看到我的进程的用户名变成了"system"。程序中用到了BitBlt抓取屏幕和EnumWindows遍历当前窗口,这个程序由系统服务来调用运行后,其他功能都正常,唯独抓屏和遍历窗口变得不正常,抓屏时抓取到的只是一幅单颜色的图像,而遍历窗口时列举出来的也只是一些隐藏的窗口甚至还有几个系统进程的名称,真是晕死!
我的问题是:
1、我的程序调试时和编译后双击运行时都正常,是不是由于运行的用户名不同而导致了抓屏和遍历窗口的不正常?
2、如果是的话,这个程序必须由系统来调用,那么应该如何解决这个问题?

解决方案 »

  1.   

    用CreateProcessAsUser以其他用户的身份运行你的程序看看吧
      

  2.   

    我现在需要解决的正是:我的一个程序需要做成系统服务,但是又要以一个普通用户的身份来调用另一个程序,应该怎么做?
    请教楼上的朋友,CreateProcessAsUser的具体用法?谢谢!!!
      

  3.   

    google搜索,关键词:CreateProcessAsUser
      

  4.   

    已经搜过了,关于VC和Delphi的介绍不少,关于VB的少得可怜而且非常简单。
    要用这个函数已当前登陆的用户身份来运行一个程序,好像还要先取得当前用户的令牌,没搜到相关的VB代码,希望高手指教一下。
      

  5.   

    那位大侠可以把下面的这段代码搞成VB的?BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
    {
     if(!lpName)
     {
      return FALSE;
     }
     HANDLE         hProcessSnap = NULL; 
        BOOL           bRet      = FALSE; 
        PROCESSENTRY32 pe32      = {0}; 
     
        hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
        if (hProcessSnap == INVALID_HANDLE_VALUE) 
            return (FALSE); 
     
        pe32.dwSize = sizeof(PROCESSENTRY32); 
     
        if (Process32First(hProcessSnap, &pe32)) 
        {  
            do 
            {
       if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
       {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
         FALSE,pe32.th32ProcessID);
        bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);
        CloseHandle (hProcessSnap); 
        return (bRet);
       }
            } 
            while (Process32Next(hProcessSnap, &pe32)); 
            bRet = TRUE; 
        } 
        else 
            bRet = FALSE;
     
        CloseHandle (hProcessSnap); 
        return (bRet);
    }BOOL RunProcess(LPCSTR lpImage)
    {
     if(!lpImage)
     {
      return FALSE;
     }
     HANDLE hToken;
     if(!GetTokenByName(hToken,"EXPLORER.EXE"))
     {
      return FALSE;
     }
     STARTUPINFO si;
     PROCESS_INFORMATION pi;
     
     ZeroMemory(&si, sizeof(STARTUPINFO));
     si.cb= sizeof(STARTUPINFO);
     si.lpDesktop = TEXT("winsta0\\default");
     
     BOOL bResult = CreateProcessAsUser(hToken,lpImage,NULL,NULL,NULL,
      FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
     CloseHandle(hToken);
     if(bResult)
     {
      OutputDebugString("CreateProcessAsUser ok!\r\n");
     }
     else
     {
      OutputDebugString("CreateProcessAsUser false!\r\n");
     }
     return bResult;
    }
      

  6.   

    'api shengming sheng nue..
    function GetTokenByName(hToken as long, byval lpName as string) as boolean
      if strptr(lpName) = 0 then gettokenbyname=false: exit function
      dim hProcessSnap as long 
      hProcessSnap = 0
      dim bRet as boolean 
      bRet = false;
      dim pe32 as processentry32
      call ZeroMemory(pe32, len(pe32)
      hProcessSnap = CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS, 0)
      if hProcessSnap = -1 then gettokenbyname=false : exit function
      pe32.dwsize = len(pe32)
      if process32First(hProcessSnap, pe32) then 
         do
            pe32.szExeFile = trim(pe32.szExeFile)
            if ucase(pe32.szExeFile) = ucase(lpName) then 
                dim hProcess as long 
                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID)
                bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, hToken)
                call CloseHandle(hProcessSnap)
                GetTokenByName = bret
                exit function
            endif
         loop while Proces32Next(hProcessSnap, pe32)
      else
         bRet = false;
      endif
      call closehandle(hProcessSnap);
      GetTokenByName = bret
      exit function
    end function function RunProcess(byval lpImage) as boolean 
      if strptr(lpImage) =0 then runprocess=false: exit function
      dim htoken as long 
      if not gettokenbyname(htoken, "explorer.exe") then 
         runprocess=false
         exit function
      endif  
      dim si as STARTPINFO;
      dim pi as PROCESS_INFORMATION
      call ZeroMemry(si, len(si))
      si.cb = len(STARTUPINFO)
      dim strtmp as string 
      strtmp = "winsta0\default"
      si.lpDestkop = strptr(strtmp)
      dim bResult as boolean
      bResult = CreateProcessAsuser(htoken, lpImage, vbnullstring, _
             vbnullstring, vbnullstring, false, NORMAL_PRIRITY_CLASS, _
             vbnullstring, vbnullstring, si, pi)
      call closeHandle(htoken)
      if bResult then 
        call outputdebugstring("createprocessasuser ok" & vbcrlf)
      else
        call outputdebugstring("createprocessasuser false" & vbcrlf)
      endif
      RunProcess = bret
    end function  
      

  7.   

    非常感谢楼上的朋友,正在调试你给的代码,所有声明我都添加上了,有几处小的笔误我也已经改过来了,但在执行到bResult = CreateProcessAsuser(htoken,lpImage,vbnullstring,vbnullstring,vbnullstring,false,NORMAL_PRIRITY_CLASS,vbnullstring, vbnullstring, si, pi)这一句时在第四个参数处提示自定义变量不可用,我又察看了一下CreateProcessAsuser的声明,此处是一个SECURITY_ATTRIBUTES类型的结构,于是我又在这个过程中加了dim ti as SECURITY_ATTRIBUTES,然后把这个vbnullstring换成ti,结果还是相同的错误提示,不知道是为什么?
      

  8.   

    申明的时候, 这个函数的 ByVal lpProcessAttributes As SECURITY_ATTRIBUTES 写成
    byval lpProcessAttributes as any
      

  9.   

    上一个问题已解决,执行到Call ZeroMemory(pe32, Len(pe32))这一句时出现dll调用约定错误,是怎么回事啊?
    Public Declare Sub ZeroMemory Lib "KERNEL32" Alias "RtlMoveMemory"  (dest As Any, ByVal numBytes As Long)
      

  10.   

    Private Type PROCESSENTRY32
           dwSize  As Long
           cntUsage  As Long
           th32ProcessID  As Long
           th32DefaultHeapID  As Long
           th32ModuleID  As Long
           cntThreads  As Long
           th32ParentProcessID  As Long
           pcPriClassBase  As Long
           dwFlags  As Long
           szExeFile  As String * 1024
    End Type
      

  11.   

    编译为exe后未出现该问题。
    问题成功解决,结贴。
    再次衷心感谢pigsanddogs朋友!!!