Programmatically registering and unregistering COM servers | CodeGuru

Programmatically registering and unregistering COM servers

In certain situations, there may be a need to programmatically register or unregister a COM server given just the name of the module that actually implements it. The specified server could be an InProcess COM server or an OutOfProcess COM server. As we all know, inprocess COM servers are registered by loading the DLL module […]

Written By
CodeGuru Staff
CodeGuru Staff
Feb 22, 1999
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

In certain situations, there may be a need to programmatically register or unregister a COM server
given just the name of the module that actually implements it. The specified server could be an
InProcess COM server or an OutOfProcess COM server. As we all know, inprocess COM servers are
registered by loading the DLL module and invoking the exported function DllRegisterServer().
The unregistration operation is performed by invoking DllUnregisterServer() instead.

OutOfProcess COM servers are registered by passing /REGSERVER on the command line for that executable.
The corresponding unregistration is done by passing /UNREGSERVER on the command line. Given this,
the only thing left is to detect if the file passed in is a DLL or an EXE.
This is easily achieved by using the GetFileVersionInfo() Platform SDK function.

I have written a C++ function to achieve all of this and the code for the same follows. This code uses
MFC but can be easily rewritten using std::basic_string() to make it usable within a pure ATL project.

HRESULT RegisterOleServer(const CString& strOleServerFile, bool bRegister)
{
	CString strTempName = strOleServerFile;
	DWORD dwFileType = VFT_UNKNOWN;
	DWORD dwVerInfoBytes;
	DWORD dwHandle;
	LPBYTE pVerInfo = NULL;
	VS_FIXEDFILEINFO* pFixedFileInfo = NULL;
	UINT uiLength;
	HRESULT hResult = S_OK;
	// Detect if the server is an InProc or OutProc server.
	dwVerInfoBytes = ::GetFileVersionInfoSize(strTempName.GetBuffer(0), &dwHandle);
	if (dwVerInfoBytes == 0)
		return HRESULT_FROM_WIN32(::GetLastError());
	// Allocate memory to hold the version information for the specified file.
	try
	{
	pVerInfo = new BYTE[dwVerInfoBytes];
	}
	catch(CMemoryException* e)
	{
	e->Delete();
	return E_OUTOFMEMORY;
	}
	// Determine the server type.
	if (::GetFileVersionInfo(strTempName.GetBuffer(0), 0, dwVerInfoBytes, pVerInfo) &&
		::VerQueryValue(pVerInfo, _T(“\”), (LPVOID*)&pFixedFileInfo, &uiLength))
	{
		//if (AfxIsValidAddress(pFixedFileInfo, sizeof(VS_FIXEDFILEINFO)))
		//{
		dwFileType = pFixedFileInfo->dwFileType;
		//}
	}
	// Cleanup resources allocated while determing the server type.
	delete pVerInfo;
	// Register the Ole Server depending on whether it is an Exe or Dll.
	switch (dwFileType)
	{
		case VFT_APP:
		{
			CString strRegServerCommand;
			if (bRegister)
			strRegServerCommand.Format(_T(“%s /REGSERVER”), (LPCTSTR)strTempName);
			else
			strRegServerCommand.Format(_T(“%s /UNREGSERVER”), (LPCTSTR)strTempName);
			// Code for ExecuteCommand() follows this function.
			hResult = ExecuteCommand(strRegServerCommand, 10000);
		}
		break;
		case VFT_DLL:
		{
			HINSTANCE hOleServerInst = NULL;
			// Load the server dll into our process space.
			hOleServerInst = ::LoadLibrary(strTempName);
			if (hOleServerInst)
			{
				HRESULT (STDAPICALLTYPE *pfnRegServer)(void);
				if (bRegister)
				{
					(FARPROC&)pfnRegServer = ::GetProcAddress(hOleServerInst, _T”DllRegisterServer”));
				}
				else
				{
					(FARPROC&)pfnRegServer = ::GetProcAddress(hOleServerInst, _T”DllUnregisterServer”));
				}
				if (pfnRegServer)
				{
					hResult = (*pfnRegServer)();
				}
				else
				{
					hResult = HRESULT_FROM_WIN32(::GetLastError());
				}
				::CoFreeLibrary(hOleServerInst);
			}
			else
			{
				hResult = HRESULT_FROM_WIN32(::GetLastError());
			}
		}
		break;
		default:
		hResult = E_INVALIDARG;
		break;
	}
	return hResult;
}
HRESULT ExecuteCommand(CString& strCommand, DWORD dwTimeout)
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	HRESULT hResult = S_OK;
	// Initialize start-up information for the new process.
	::ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	::ZeroMemory(&pi, sizeof(pi));
	if (::CreateProcess(NULL, strCommand.GetBuffer(0), NULL, NULL, FALSE, NULL, NULL, NULL,
	&si, &pi))
	{
		if (dwTimeout)
		{
			::WaitForSingleObject(pi.hProcess, dwTimeout);
			::CloseHandle(pi.hProcess);
			::CloseHandle(pi.hThread);
		}
	}
	else
		hResult = HRESULT_FROM_WIN32(::GetLastError());
		return hResult;
}

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.