First create a DLL project named ServMgrDll, create a new class, including the header file ServConfig.h and the cpp file ServConfig.cpp.
The code for the class is as follows:
.h:
#pragma once /* If there is no definition: ServConfigAPI, then ServConfigAPI is defined as: _declspec(dllimport), The compiler knows that the executable source file needs to import certain functions from the DLL module. */ #ifdef ServConfigAPI #else #define ServConfigAPI extern "C" _declspec(dllimport) #endif class CServItem { public: CString m_strServName; CString m_strServDispName; DWORD m_dwServStatus; CString m_strBinPath; DWORD m_dwStartType; CString m_strDescription; CServItem *m_pNext; CServItem () { m_dwServStatus = 0; m_pNext = NULL; } }; /******Export class: CServConfig ******/ class __declspec(dllexport) CServConfig { public: CServConfig(void); ~CServConfig(void); public: CServItem *EnumServList(); BOOL GetServPathAndStartType(LPCTSTR lpszServName, CServItem &tItem); CString GetServDescription(LPCTSTR lpszServName); void FreeServList(CServItem *pServList); };
.cpp :
#include "StdAfx.h" /*Define before the header file: ServConfigAPI, which means to export some functions in the DLL module*/ #define ServConfigAPI extern "C" _declspec(dllexport) #include "ServConfig.h" CServConfig::CServConfig(void) { } CServConfig::~CServConfig(void) { } CServItem *CServConfig::EnumServList() { SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if ( !hSCM ) { return NULL; } CServItem *pServHeader = NULL, *pServPre = NULL, *pServNext = NULL; LPENUM_SERVICE_STATUS pServStatus = NULL; DWORD dwBytesNeeded = 0, dwServCound = 0, dwResume = 0, dwRealBytes = 0; BOOL bRet = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwServCound, &dwResume); if ( !bRet && GetLastError() == ERROR_MORE_DATA ) { dwRealBytes = dwBytesNeeded; pServStatus = new ENUM_SERVICE_STATUS[dwRealBytes+1]; ZeroMemory(pServStatus, dwRealBytes+1); bRet = EnumServicesStatus(hSCM, SERVICE_WIN32, SERVICE_STATE_ALL, pServStatus, dwRealBytes, &dwBytesNeeded, &dwServCound, &dwResume); if ( !bRet ) { CloseServiceHandle(hSCM); return NULL; } }else{ CloseServiceHandle(hSCM); return NULL; } pServPre = pServNext; for( DWORD dwIdx = 0; dwIdx < dwServCound; dwIdx++ ) { pServNext = new CServItem; pServNext->m_strServName = pServStatus[dwIdx].lpServiceName; pServNext->m_strServDispName = pServStatus[dwIdx].lpDisplayName; pServNext->m_dwServStatus = pServStatus[dwIdx].ServiceStatus.dwCurrentState; GetServPathAndStartType(pServNext->m_strServName, *pServNext); pServNext->m_strDescription = GetServDescription(pServNext->m_strServName); (pServHeader == NULL) ? (pServHeader = pServNext) : pServHeader; (pServPre == NULL) ? (pServPre = pServNext) : (pServPre->m_pNext = pServNext, pServPre = pServNext); } CloseServiceHandle(hSCM); delete [] pServStatus; return pServHeader; } BOOL CServConfig::GetServPathAndStartType(LPCTSTR lpszServName, CServItem &tItem) { BOOL bRet = FALSE; SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCM == NULL){ return FALSE; } SC_HANDLE hSvc = OpenService(hSCM, lpszServName, SERVICE_QUERY_CONFIG); if (hSvc == NULL){ CloseServiceHandle(hSCM); return FALSE; } // for the QueryServiceConfig; QUERY_SERVICE_CONFIG *pServCfg = NULL; DWORD cbBytesNeeded = 0, cbBufferSize = 0; bRet = QueryServiceConfig(hSvc, NULL, 0, &cbBytesNeeded); if (bRet == FALSE){ if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ){ pServCfg = new QUERY_SERVICE_CONFIG[cbBytesNeeded+1]; ZeroMemory(pServCfg, cbBytesNeeded+1); cbBufferSize = cbBytesNeeded; cbBytesNeeded = 0; }else{ goto __Error_End; } } bRet = QueryServiceConfig(hSvc, pServCfg, cbBufferSize, &cbBytesNeeded); if (bRet == FALSE){ goto __Error_End; } tItem.m_strBinPath = pServCfg->lpBinaryPathName; tItem.m_dwStartType = pServCfg->dwStartType; bRet = TRUE; if ( pServCfg ) { delete [] pServCfg; } __Error_End: CloseServiceHandle(hSvc); CloseServiceHandle(hSCM); return bRet; } CString CServConfig::GetServDescription(LPCTSTR lpszServName) { CString strResult; BOOL bRet = FALSE; SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hSCM == NULL){ return strResult; } SC_HANDLE hSvc = OpenService(hSCM, lpszServName, SERVICE_QUERY_CONFIG); if (hSvc == NULL){ CloseServiceHandle(hSCM); return strResult; } //for the QueryServiceConfig2; DWORD dwNeeded = 0, dwLen = 0; LPSERVICE_DESCRIPTION pDescripTion = NULL; bRet = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwNeeded); if ( !bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { dwLen = dwNeeded + 1; pDescripTion = new SERVICE_DESCRIPTION[dwLen]; ZeroMemory(pDescripTion, dwLen); if ( QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)pDescripTion, dwLen, &dwNeeded) ) { strResult = pDescripTion->lpDescription; } } CloseServiceHandle(hSvc); CloseServiceHandle(hSCM); return strResult; } void CServConfig::FreeServList(CServItem *pServList) { CServItem *pT = NULL; while (pServList) { pT = pServList->m_pNext; delete pServList; pServList = pT; } }
Compile and generate, two files will be generated: ServMgrDll.lib, ServMgrDll.dll.
2. Use the exported class:
First, include the import library generated by the dynamic library: #pragma comment(lib,"D:\\drawing programming\\ServMgrDll\\Release\\ServMgrDll.lib");
Second, add the header file ServConfig.h created in the dll project to the executable project, including the header file: #include "ServConfig.h";
Again, put the dynamic library together with the executable .exe.
as follows:
// DllUse.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "ServConfig.h" #include <iostream> using namespace std; #pragma comment(lib,"D:\\drawing programming\\ServMgrDll\\Release\\ServMgrDll.lib") int _tmain(int argc, _TCHAR* argv[]) { CServConfig m_ServCfg; CServItem * m_pServList = NULL; CServItem * m_pHeader = m_ServCfg.EnumServList(); if ( !m_pHeader ) { return 0; } TCHAR szbuf[MAX_PATH] = {0}; m_pServList = m_pHeader; for ( int idx = 0; m_pServList != NULL; idx++ ) { _tcscpy(szbuf,m_pServList->m_strServName.GetBuffer()); _tprintf(_T("%s\n"),szbuf); m_pServList = m_pServList->m_pNext; } m_ServCfg.FreeServList(m_pHeader); system("pause"); return 0; }
3. To use CString in MFC in win32 dynamic library, the following configuration is required:
First, include the header files, noting the order:
#include <afx.h> #include <windows.h>
Secondly, Properties->C/C++->Code Generation->Runtime Library: Multithreading (/MT);
Finally, add the following code to dllmain.cpp:
#ifdef _X86_ extern "C" { int _afxForceUSRDLL; } #else extern "C" { int __afxForceUSRDLL; } #endifcomplete!