枚举Windows系统服务,通过进程ID取服务名

时间:2023-02-08 16:07:53


//枚举Windows系统服务

//使用到的函数以及MSDN的说明如下:
//1、OpenSCManager说明
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms684323(v=vs.85).aspx

//2、EnumServicesStatusEx说明
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms682640(v=vs.85).aspx

//3、CloseServiceHandle说明
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms682028(v=vs.85).aspx

// 测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <windows.h>
int main(int argc, char *argv[])
{
	LONG lRet = 0;
	BOOL bRet = FALSE;
	SC_HANDLE hSCM = NULL;              // 服务数据库句柄
	char *pBuf = NULL;                  // 缓冲区指针
	DWORD dwBufSize = 0;                // 传入的缓冲长度
	DWORD dwBufNeed = 0;                // 需要的缓冲长度
	DWORD dwNumberOfService = 0;        // 返回的服务个数
	ENUM_SERVICE_STATUS_PROCESS *pServiceInfo = NULL;   // 服务信息

	// 建立了一个到服务控制管理器的连接,并打开指定的数据库
	hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
	if(NULL == hSCM)
	{
		printf("OpenSCManager error.\n");
		return -1;
	}

	// 获取需要的缓冲区大小
	EnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, 
		NULL, dwBufSize, &dwBufNeed, &dwNumberOfService, NULL, NULL);

	// 多设置存放1个服务信息的长度
	dwBufSize = dwBufNeed + sizeof(ENUM_SERVICE_STATUS_PROCESS);
	pBuf = (char *)malloc(dwBufSize);
	if(NULL == pBuf)
	{
		printf("malloc error.\n");
		return -1;
	}
	memset(pBuf, 0, dwBufSize);

	// 获取服务信息
	bRet = EnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, 
		(LPBYTE)pBuf, dwBufSize, &dwBufNeed, &dwNumberOfService, NULL, NULL);
	if(bRet == FALSE)
	{
		printf("EnumServicesStatusEx error.\n");
		::CloseServiceHandle(hSCM);
		free(pBuf);
		return -1;
	}
	// 关闭打开的服务句柄
	bRet = ::CloseServiceHandle(hSCM);
	if(bRet == FALSE)
	{
		printf("CloseServiceHandle error.\n");
	}
	printf("Service Num:%d\n", dwNumberOfService);

	pServiceInfo = (LPENUM_SERVICE_STATUS_PROCESS)pBuf;
	// 打印取得的服务信息
	for(unsigned int i = 0; i < dwNumberOfService; i++)
	{
		printf("----------%d----------\n", i);
		printf("DisplayName \t\t : %s \n", pServiceInfo[i].lpDisplayName);
		printf("ServiceName \t\t : %s \n", pServiceInfo[i].lpServiceName);
		printf("ServiceType \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwServiceType);
		printf("CurrentState \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwCurrentState);
		printf("ControlsAccepted \t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwControlsAccepted);
		printf("Win32ExitCode \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwWin32ExitCode);
		printf("ServiceSpecificExitCode  : %d \n", pServiceInfo[i].ServiceStatusProcess.dwServiceSpecificExitCode);
		printf("CheckPoint \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwCheckPoint);
		printf("WaitHint \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwWaitHint);
		printf("Process Id \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwProcessId);
		printf("ServiceFlags \t\t : %d \n", pServiceInfo[i].ServiceStatusProcess.dwServiceFlags);
	}
	free(pBuf);
	system("PAUSE");
	return 0;
}


// 既然能够获取到所有的服务信息,
// 那么根据进程ID查询该进程是否为服务,取得服务名等一系列的操作就可以按自己的需求来完成了
// 获取进程ID GetCurrentProcessId()