就像在本机上运行“任务管理器”一样,察看局域网内的机器的进程。

解决方案 »

  1.   

    <<第四部分:从PDH中取得本地/远程系统进程信息>>  前面说的三种方法都只能枚举本地的系统进程,如何枚举远程系统的进程呢?目前我只知道从PDH中取得进程信息。  OK!我先简单的说说PDH是什么东西,hoho~难的偶也不会。PDH是英文Performance Data Helper的缩写,Windows NT一直在更新这个称为Performance Data的数据库,这个数据库包含了大量的信息,例如CPU使用率,内存使用率,系统进程信息等等一大堆有用的信息,可以通过注册表函数来访问。注意哦,Windows 9x中并没有配置这个数据库。但是,这个数据库中的信息布局很复杂,很多人并不愿意使用它,包括我。而且刚开始的时候,它也没有自己特定的函数,只能通过现有的注册表函数来操作。后来,为了使该数据库的使用变得容易,MS开发了一组Performance Data Helper函数,包含在PDH.DLL文件中。Windows 2000默认是允许远程注册表操作的,所以我们就可以通过连接远程系统的注册表,从它的PDH中取得我们所需要的系统进程信息了,当然这需要远程系统的Admin权限。OK!我们下面所举的例子是直接利用注册表函数来从本地/远程系统的PDH数据库中取得我们所需要的数据的,我们并没有利用PDH API。    程序代码如下:
      

  2.   

    /**************************************************************************Module:ps.cAuthor:[email protected]:ey4sHttp://www.ey4s.orgDate:2001/6/23**************************************************************************/#include #include #include #define INITIAL_SIZE    51200#define EXTEND_SIZE     12800#define REGKEY_PERF     "software\\microsoft\\windows nt\\currentversion\\perflib"#define REGSUBKEY_COUNTERS "Counters"#define PROCESS_COUNTER   "process"#define PROCESSID_COUNTER  "id process"#define UNKNOWN_TASK    "unknown" #define MaxProcessNum      52//最大进程数量#pragma comment(lib,"mpr.lib")typedef struct ProcessInfo{char ProcessName[128];DWORD dwProcessID;}pi;void banner();int ConnIPC(char *,char *,char *);DWORD GetProcessInfo(pi *,char *,char *,char *);int main(int argc,char **argv){int i,iRet;pi TaskList[MaxProcessNum];banner();if(argc==1){iRet=GetProcessInfo(TaskList,NULL,NULL,NULL);  printf("\nProcess Info for [LOCAL]:");}else if(argc==4){iRet=GetProcessInfo(TaskList,argv[1],argv[2],argv[3]);printf("\nProcess Info for [%s]:",argv[1]);}else{printf("\nUsage:%s ",argv[0]);return 1;}if(iRet>0)   for(i=0,printf("\nProcessName     ProcessID");i 
    printf("\n%-20s %d",TaskList[i].ProcessName,TaskList[i].dwProcessID),i++);    return 0;}
      

  3.   

    DWORD GetProcessInfo(pi *ProList,char *ip,char *user,char *pass){  DWORD rc,dwType,dwSize,i,dwProcessIdTitle,dwProcessIdCounter,dwRet=-1;  HKEY             hKeyNames;  LPSTR            buf = NULL,p,p2;  CHAR             szSubKey[1024],szProcessName[MAX_PATH];  PPERF_DATA_BLOCK       pPerf;  PPERF_OBJECT_TYPE      pObj;  PPERF_INSTANCE_DEFINITION  pInst;  PPERF_COUNTER_BLOCK     pCounter;  PPERF_COUNTER_DEFINITION   pCounterDef;  HKEY      ghPerfKey =NULL, // get perf data from this keyghMachineKey = NULL; // get title index from this key  BOOL bRemote=FALSE;  // Look for the list of counters. Always use the neutral  // English version, regardless of the local language. We  // are looking for some particular keys, and we are always  // going to do our looking in English. We are not going  // to show the user the counter names, so there is no need  // to go find the corresponding name in the local language.    __try    {       if((ip)&&(user)&&(pass))       {           if(ConnIPC(ip,user,pass)!=0)           {              printf("\nConnect to %s failed.",ip);              __leave;           }           else              bRemote=TRUE;      }       //连接本地or远程注册表       if(RegConnectRegistry(ip,HKEY_PERFORMANCE_DATA,           &ghPerfKey)!=ERROR_SUCCESS)       {           printf("\nRegConnectRegistry() 1 failed:%d",GetLastError());           __leave;       }`   if(RegConnectRegistry(ip,HKEY_LOCAL_MACHINE,&ghMachineKey)!=ERROR_SUCCESS)       {           printf("\nRegConnectRegistry() 2 failed:%d",GetLastError());           __leave;       }sprintf( szSubKey, "%s\\%03x", REGKEY_PERF,MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL));if(RegOpenKeyEx(ghMachineKey,szSubKey,0,KEY_READ,&hKeyNames)!=ERROR_SUCCESS)           __leave;       // 从counter names取得需要的缓冲区大小if(RegQueryValueEx(hKeyNames,REGSUBKEY_COUNTERS,NULL,&dwType,NULL,&dwSize)!= ERROR_SUCCESS)  __leave;       //分配内存       buf = (LPSTR) malloc( dwSize );       if (buf == NULL)           __leave;       memset( buf, 0, dwSize );       // read the counter names from the registryif(RegQueryValueEx(ghPerfKey,REGSUBKEY_COUNTERS,NULL,&dwType,(LPBYTE) buf,&dwSize)!= ERROR_SUCCESS)           __leave;       // now loop thru the counter names looking for the following counters:       //   1. "Process"     process name       //   2. "ID Process"    process id       // the buffer contains multiple null terminated strings and then       // finally null terminated at the end. the strings are in pairs of       // counter number and counter name.       p = buf;       while (*p)       {           if (p>buf)             for( p2=p-2; isdigit(*p2); p2--) ;           if (stricmp(p, PROCESS_COUNTER) == 0)           {              // look backwards for the counter number             for( p2=p-2; isdigit(*p2); p2--) ;              strcpy( szSubKey, p2+1 );           }           else if (stricmp(p, PROCESSID_COUNTER) == 0)           {              // look backwards for the counter number             for( p2=p-2; isdigit(*p2); p2--) ;              dwProcessIdTitle = atol( p2+1 );           }           // next string           p += (strlen(p) + 1);       }       // free the counter names buffer       free( buf );       // allocate the initial buffer for the performance data       dwSize = INITIAL_SIZE;       buf = (LPSTR) malloc( dwSize );       while (TRUE)       {           if (buf == NULL)              __leave;           memset( buf, 0, dwSize );           rc=RegQueryValueEx(ghPerfKey,szSubKey,NULL,&dwType,(LPBYTE) buf,&dwSize);           pPerf = (PPERF_DATA_BLOCK) buf;           // check for success and valid perf data block signature           if ((rc == ERROR_SUCCESS) &&                 (dwSize > 0) &&                 (pPerf)->Signature[0] == (WCHAR)'P' &&                 (pPerf)->Signature[1] == (WCHAR)'E' &&                 (pPerf)->Signature[2] == (WCHAR)'R' &&                 (pPerf)->Signature[3] == (WCHAR)'F' )              break;           // if buffer is not big enough, reallocate and try again           if (rc == ERROR_MORE_DATA)           {              dwSize += EXTEND_SIZE;              buf = (LPSTR) realloc( buf, dwSize );           }           else __leave;       }       // set the perf_object_type pointer       pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);       //loop thru the performance counter definition records looking       //for the process id counter and then save its offset   pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);    for (i=0; i<(DWORD)pObj->NumCounters; i++)       {           if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle)           {              dwProcessIdCounter = pCounterDef->CounterOffset;              break;           }           pCounterDef++;       }    pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);       // loop thru the performance instance data extracting each process name       // and process id       for (i=0; i < (DWORD)pObj->NumInstances-1 && i 
           {           // pointer to the process name           p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);           // convert it to ascii           rc = WideCharToMultiByte( CP_ACP,0,(LPCWSTR)p,-1,szProcessName,sizeof(szProcessName),NULL,NULL);           // if we cant convert the string then use a default value           if (!rc) strcpy( ProList[i].ProcessName, UNKNOWN_TASK );           else strncpy(ProList[i].ProcessName, szProcessName,sizeof(ProList[i].ProcessName)-1);           // get the process id       pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);  ProList[i].dwProcessID = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));           // next process  pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);        }       dwRet=i;    }//end of try    __finally    {       if (buf) free( buf );       RegCloseKey( hKeyNames );       RegCloseKey( HKEY_PERFORMANCE_DATA );       if(bRemote)       {           char tmp[52],tmp2[96];           strncpy(tmp,ip,sizeof(tmp)-1);           wsprintf(tmp2,"\\\\%s\\ipc$",tmp);           WNetCancelCon
      

  4.   

    上面的如果远程注册表给禁掉了就用不了了。
    还有一个工具包叫做pstools的,里面有好些东西利用。其中有一个工具能够看别的机器的内容,不过不是通过注册表。可以利用。
      

  5.   

    其实安装了vc6后,有一个工具叫process viewer的,就是按照注册表的方法做的。也可以利用。
      

  6.   

    非常感谢。
    那么如何设置“远程机器允许IPC连接和远程操作注册表”呢?
      

  7.   

    如果是默认安装的NT都可以的。
    如果不行,就要手动打开相应的服务。
    pslist真的不需要远程注册表服务?