Export a class using a dynamic library DLL

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; }
#endif
complete!


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326311858&siteId=291194637