본문 바로가기
C++/MFC

C++에서 COM , COM+ 메서드 호출 예제

by Hwoarang757 2021. 2. 7.

예제는 UserCipher.Cipher.1 로 등록된 명칭의 COM 모듈의 

getSessionInfo라는 함수를 호출 하고  , 매개변수를 192.168.100.1로 설정 하였습니다.

리턴 형식은 Int 형식을 받는 예제 입니다.

 

출처 : 

docs.microsoft.com/ko-kr/previous-versions/office/troubleshoot/office-developer/automate-excel-from-c

 

// ComplusTest.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include "ComplusTest.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 유일한 응용 프로그램 개체입니다.

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	HMODULE hModule = ::GetModuleHandle(NULL);

	if (hModule != NULL)
	{
		// MFC를 초기화합니다. 초기화하지 못한 경우 오류를 인쇄합니다.
		if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
		{
			// TODO: 오류 코드를 필요에 따라 수정합니다.
			_tprintf(_T("심각한 오류: MFC를 초기화하지 못했습니다.\n"));
			nRetCode = 1;
		}
		else
		{
			// TODO: 응용 프로그램의 동작은 여기에서 코딩합니다.
			ComExecute();

		}
	}
	else
	{
		// TODO: 오류 코드를 필요에 따라 수정합니다.
		_tprintf(_T("심각한 오류: GetModuleHandle 실패\n"));
		nRetCode = 1;
	}

	return nRetCode;
}


HRESULT AutoWrap(int autoType , VARIANT *pvResult, IDispatch *pDisp , LPOLESTR ptName , int cArgs...) {

	HRESULT hr;
	va_list marker;
	va_start(marker , cArgs);

	if(!pDisp) {
		cout << "Error NULL IDispatch passed to AutoWrap()" << endl;
		return -99;
	}

	//Variable used
	DISPPARAMS dp = { NULL , NULL, 0 ,0 };
	DISPID dispidNamed = DISPID_PROPERTYPUT;
	DISPID dispID;

	char buf[200];
	char szName[200];

	//Convert down to ANSI 
	WideCharToMultiByte(CP_ACP,0 , ptName , -1 , szName , 256 , NULL, NULL);
	
	//Get DISPID for name passed 
	hr = pDisp->GetIDsOfNames(IID_NULL,&ptName,1,LOCALE_USER_DEFAULT , &dispID);
	if(FAILED(hr)) {
		sprintf(buf , "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%0lx",szName , hr);
		cout << buf << endl;
		return hr;
	}

	// Allocate memory for arguments...
	VARIANT *pArgs = new VARIANT[cArgs + 1];
	// Extract arguments
	for(int i = 0 ; i <cArgs ; i++) {
		pArgs[i] = va_arg(marker , VARIANT);
	}

	//Build DISPPARAMS
	dp.cArgs = cArgs;
	dp.rgvarg = pArgs;

	//Handle special-case for property-puts!
	if(autoType & DISPATCH_PROPERTYPUT) {
		dp.cNamedArgs = 1;
		dp.rgdispidNamedArgs = &dispidNamed;
	}

	//Make the call!
	hr = pDisp->Invoke(dispID,IID_NULL,LOCALE_SYSTEM_DEFAULT , autoType , &dp , pvResult ,NULL ,NULL);
	if(FAILED(hr)) {
		sprintf(buf , "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx" , szName,dispID,hr);
		cout << buf << endl;
		return hr;
	}
	va_end(marker);
	delete[] pArgs;

	return hr;
}

void ComExecute() {
	//Initialize COM for this thread...
	CoInitialize(NULL);
	
	//Get CLSID for our server...
	CLSID clsid;
	HRESULT hr = CLSIDFromProgID(L"UserCipher.Cipher.1",&clsid);

	IDispatch *pChiper;
	hr = CoCreateInstance(clsid , NULL , CLSCTX_LOCAL_SERVER , IID_IDispatch , (void **)&pChiper);
	if(FAILED(hr)) {
		cout << "Cipher not registered properly" << endl;
		return;
	}

	VARIANT parm;
	
		parm.vt = VT_BSTR;
		parm.bstrVal = ::SysAllocString(L"192.168.100.1");

		VARIANT result;
		VariantInit(&result);
		AutoWrap(DISPATCH_METHOD , &result , pChiper , L"getSessionInfo" , 1, parm);
		VariantClear(&parm);

		cout<< "getSessionInfo=[" << result.intVal << "]" << endl;
        
     CoUninitialize();
}