列举本地所有网络的活动进程

来源:互联网 发布:风险矩阵图依据 编辑:程序博客网 时间:2024/06/05 22:56

任务: 列举本机所有网络活动的进程信息,包括协议类型、进程ID及其名称、本地地址及对应端口、远程地址及对应端口、当前连接状态信息。

环境: Win7 + VC++2010

注:(1)本例程适用于Windows Vista / 7, VS2010以上版本(VS2008未测试),不适用于VS2005以下版本。

        (2)VS2005中没有TCP_TABLE_CLASS 的定义

        (3)在windows vista以及更高版本,AllocateAndGetTcpExTableFromStack函数已经被废弃,由GetTcpTable和GetUdpTable替代,Udp相关函数类似.

步骤:

1. 创建MFC单文档程序,并在向导中选中Win socket ,视图基类选为CListView;

2. 在View类的头文件中添加包含文件和库:

#include <WinSock2.h>#include <IPHlpApi.h>#include <TlHelp32.h>#pragma comment(lib, "WS2_32.lib")#pragma comment(lib, "Iphlpapi.lib")

3. 在View类的PreCreateWindow函数中设置视图风格:

BOOL CNetProcessView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying//  the CREATESTRUCT cscs.style = (cs.style & (~LVS_TYPEMASK) | LVS_REPORT);cs.style |= LVS_AUTOARRANGE;return CListView::PreCreateWindow(cs);}
4. 由于包含的头文件中没有GetExtendedTcpTable()函数的定义,因此需要自己定义导出函数原型,如下:

//定义函数指针,以便调用GetExtendedTcpTable()typedef   DWORD   (WINAPI *PGetExtendedTcpTable)( _Out_    PVOID pTcpTable,_Inout_  PDWORD pdwSize,_In_     BOOL bOrder,_In_     ULONG ulAf,_In_     TCP_TABLE_CLASS TableClass,_In_     ULONG Reserved); // GetExtendedUdpTable()typedef DWORD (WINAPI *PGetExtendedUdpTable)(_Out_    PVOID pUdpTable,_Inout_  PDWORD pdwSize,_In_     BOOL bOrder,_In_     ULONG ulAf,_In_     UDP_TABLE_CLASS TableClass,_In_     ULONG Reserved);

5. 编写核心函数,获取运行Tcp,Udp协议的进程相关信息:

BOOL CNetProcessView::GetNetProcess(void){PMIB_TCPTABLE_OWNER_PID pTcpTable = NULL;PMIB_UDPTABLE_OWNER_PID pUdpTable = NULL;DWORD dwSize = 0;DWORD dwRetVal = 0;char szLocalAddr[128];char szRemoteAddr[128];in_addr inadLocal, inadRemote;char strState[128];DWORD dwRemotePort = 0;char chID[8];char chName[30];//系统内所有进程HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if(hProcessSnap == INVALID_HANDLE_VALUE){AfxMessageBox("Failed to take process snapshot. Process names will not be shown. ");return -1;}CListCtrl &listView = GetListCtrl();// 获取扩展函数的入口地址PGetExtendedTcpTable GetExtendedTcpTable;PGetExtendedUdpTable GetExtendedUdpTable;HMODULE hModule = ::LoadLibrary("iphlpapi.dll");GetExtendedTcpTable = (PGetExtendedTcpTable)::GetProcAddress(hModule, "GetExtendedTcpTable");GetExtendedUdpTable = (PGetExtendedUdpTable)::GetProcAddress(hModule, "GetExtendedUdpTable");////////////////////////////////////////////////////////////////////////////打印TCP扩展连接表信息if(GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)== ERROR_INSUFFICIENT_BUFFER){pTcpTable = (PMIB_TCPTABLE_OWNER_PID)::GlobalAlloc(GPTR, dwSize);if(GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)== NO_ERROR){for(int i=0; i<(pTcpTable->dwNumEntries); i++){listView.InsertItem(i, _T("TCP"));//ProcessIDmemset(chID, '\0', 8);sprintf(chID, "%d", pTcpTable->table[i].dwOwningPid);listView.SetItemText(i, 1, chID);//Process Namememset(chName, '\0', 30);listView.SetItemText(i, 2, ProcessID2Name(hProcessSnap, pTcpTable->table[i].dwOwningPid, chName));//Local Address&PortinadLocal.s_addr = pTcpTable->table[i].dwLocalAddr;sprintf(szLocalAddr, "%s : %u", inet_ntoa(inadLocal), ntohs((unsigned short)(0x0000ffff & pTcpTable->table[i].dwLocalPort)));listView.SetItemText(i, 3, szLocalAddr);//Stateswitch(pTcpTable->table[i].dwState){case MIB_TCP_STATE_CLOSED:strcpy(strState, "CLOSED");break;case MIB_TCP_STATE_TIME_WAIT:strcpy(strState, "TIME_WAIT");break;case MIB_TCP_STATE_LAST_ACK:strcpy(strState, "LAST_ACK");break;case MIB_TCP_STATE_CLOSING:strcpy(strState, "CLOSING");break;case MIB_TCP_STATE_CLOSE_WAIT:strcpy(strState, "CLOSE_WAIT");break;case MIB_TCP_STATE_FIN_WAIT1:strcpy(strState, "FIN_WAIT1");break;case MIB_TCP_STATE_ESTAB:strcpy(strState, "ESTAB");break;case MIB_TCP_STATE_SYN_RCVD:strcpy(strState, "SYN_RCVD");break;case MIB_TCP_STATE_SYN_SENT:strcpy(strState, "SYN_SENT");break;case MIB_TCP_STATE_LISTEN:strcpy(strState, "LISTEN");break;case MIB_TCP_STATE_DELETE_TCB:strcpy(strState, "DELETE");break;default:printf("Error: unknown state!\n");break;}listView.SetItemText(i, 5, strState);//Remote Address&Port// 远程IP地址inadRemote.s_addr = pTcpTable->table[i].dwRemoteAddr;// 远程端口if(strcmp(strState, "LISTEN") != 0){dwRemotePort = pTcpTable->table[i].dwRemotePort;}else{dwRemotePort = 0;}sprintf(szRemoteAddr, "%s:%u", inet_ntoa(inadRemote), ntohs((unsigned short)(0x0000FFFF & dwRemotePort)));listView.SetItemText(i, 4, szRemoteAddr);}}}//////////////////////////////////////////////////////////////////////////// 打印UDP信息表if(GetExtendedUdpTable(pUdpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0)== ERROR_INSUFFICIENT_BUFFER){pUdpTable = (PMIB_UDPTABLE_OWNER_PID)::GlobalAlloc(GPTR, dwSize);if(GetExtendedUdpTable(pUdpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0)== NO_ERROR){for(int i = 0; i < (pUdpTable->dwNumEntries); ++i){listView.InsertItem(i,_T("UDP"));//Process IDmemset(chID,'\0',8);sprintf(chID,"%d",pUdpTable->table[i].dwOwningPid);listView.SetItemText(i,1,chID);//Process Namememset(chName,'\0',30);listView.SetItemText(i,2,ProcessID2Name(hProcessSnap,pUdpTable->table[i].dwOwningPid,chName));// 本地IP地址inadLocal.s_addr = pUdpTable->table[i].dwLocalAddr;sprintf(szLocalAddr,  "%s:%u", inet_ntoa(inadLocal), ntohs((unsigned short)(0x0000FFFF & pUdpTable->table[i].dwLocalPort)));listView.SetItemText(i,3,szLocalAddr);}}}::CloseHandle(hProcessSnap);::GlobalFree(pTcpTable);::GlobalFree(pUdpTable);return 0;}

其中根据进程ID获得进程名称的函数ProcessID2Name()实现:

PCHAR ProcessID2Name(HANDLE hProcessSnap, DWORD ProcessId, PCHAR ProcessName){PROCESSENTRY32 processEntry;processEntry.dwSize = sizeof(processEntry);// 找不到的话,默认进程名为“Unkown”strcpy(ProcessName, "Unkown");if(!::Process32First(hProcessSnap, &processEntry)) return ProcessName;do {if(processEntry.th32ProcessID == ProcessId) // 就是这个进程{strcpy(ProcessName, processEntry.szExeFile);break;}}while(::Process32Next(hProcessSnap, &processEntry));return ProcessName;}

6. 调用函数GetNetProcess并显示:

void CNetProcessView::OnInitialUpdate(){CListView::OnInitialUpdate();// TODO: You may populate your ListView with items by directly accessing//  its list control through a call to GetListCtrl().CListCtrl &listView = GetListCtrl();listView.InsertColumn(0, _T("连接类型"), LVCFMT_LEFT, 85, 0);listView.InsertColumn(1, _T("进程ID"), LVCFMT_LEFT, 150, 0);listView.InsertColumn(2, _T("进程名称"), LVCFMT_LEFT, 155, 0);listView.InsertColumn(3, _T("本地地址"), LVCFMT_LEFT, 175, 0);listView.InsertColumn(4, _T("远程地址"), LVCFMT_LEFT, 175, 0);listView.InsertColumn(5, _T("连接状态"), LVCFMT_LEFT, 200, 0);GetNetProcess();}
贴一张运行图:


OK!