Tag | COM
'Study/COM'에 해당되는 글 2건
- 2007/12/06 COM 실습 - 바로가기, 태스크바 (6)
- 2007/12/04 COM - 기본( 등록, 사용 )
1) 만들어 놓은 클래스 라이브러리를 멤버변수로 선언하여 사용하게 되면 강한 결합을 하게 된다.
2) 그래서, 인터페이스를 사용하여 약한 결합을 만드는데 이게 바로 COM이 하는 역할이다.
3) 3개의 함수는 QueryInterface, AddRef, Release 를 반드시 구현해 줘야 한다.
4) 컴포넌트가 객체생성을 책임져야 하므로 반드시 IUnknown 를 최상위 부모로 하여 상속되어야 한다.
5) CreateInstance, DllGetClassObject 를 사용하여 객체를 생성해줘야 한다.
6) 이모든 과정을 단순화 한 것이 ATL, COM+ 이다...그래도 어렵다..ㅜ_ㅜ..
2) 그래서, 인터페이스를 사용하여 약한 결합을 만드는데 이게 바로 COM이 하는 역할이다.
3) 3개의 함수는 QueryInterface, AddRef, Release 를 반드시 구현해 줘야 한다.
4) 컴포넌트가 객체생성을 책임져야 하므로 반드시 IUnknown 를 최상위 부모로 하여 상속되어야 한다.
5) CreateInstance, DllGetClassObject 를 사용하여 객체를 생성해줘야 한다.
6) 이모든 과정을 단순화 한 것이 ATL, COM+ 이다...그래도 어렵다..ㅜ_ㅜ..
- regsvr32 DLL명
- Com.dll 을 레지스트리(HKEY_CLASSES_ROOT\CLSID) 에 등록해준다.
1. IFace.h ( 인터페이스ID, 클래스ID 를 등록한다 )
more..
#ifndef _IFACE_H
#define _IFACE_H#undef _UNICODE
#undef UNICODE
#include <windows.h>
#ifndef interface
#define interface struct
#endif
// 모든 interface는 반드시 IUnknown 에서 상속되어야 한다.
// 모든 전화기의 interface
interface IPhone : public IUnknown
{
virtual void Calling( char* number ) = 0;
};
// 모든 계산기의 interface
interface ICalc : public IUnknown
{
virtual int Plus( int a, int b ) = 0;
virtual int Minus( int a, int b ) = 0;
};
// 모든 interface의 고유한 번호를 부여 해야 한다.
// {10A4AA2B-EEBE-4491-B91E-F610AA3DB6C3}
static const IID IID_IPhone = // Interface ID
{ 0x10a4aa2b, 0xeebe, 0x4491, { 0xb9, 0x1e, 0xf6, 0x10, 0xaa, 0x3d, 0xb6, 0xc3 } };
// {76AAF296-23B4-43de-8107-7381DEADD769}
static const IID IID_ICalc =
{ 0x76aaf296, 0x23b4, 0x43de, { 0x81, 0x7, 0x73, 0x81, 0xde, 0xad, 0xd7, 0x69 } };
// Com 자체에도 ID를 부여한다.
// {026E86AC-95FA-4166-B77E-764BFAE33D4C}
static const CLSID CLSID_AnyCall = // class ID
{ 0x26e86ac, 0x95fa, 0x4166, { 0xb7, 0x7e, 0x76, 0x4b, 0xfa, 0xe3, 0x3d, 0x4c } };
#endif // _IFACE_H
#define _IFACE_H#undef _UNICODE
#undef UNICODE
#include <windows.h>
#ifndef interface
#define interface struct
#endif
// 모든 interface는 반드시 IUnknown 에서 상속되어야 한다.
// 모든 전화기의 interface
interface IPhone : public IUnknown
{
virtual void Calling( char* number ) = 0;
};
// 모든 계산기의 interface
interface ICalc : public IUnknown
{
virtual int Plus( int a, int b ) = 0;
virtual int Minus( int a, int b ) = 0;
};
// 모든 interface의 고유한 번호를 부여 해야 한다.
// {10A4AA2B-EEBE-4491-B91E-F610AA3DB6C3}
static const IID IID_IPhone = // Interface ID
{ 0x10a4aa2b, 0xeebe, 0x4491, { 0xb9, 0x1e, 0xf6, 0x10, 0xaa, 0x3d, 0xb6, 0xc3 } };
// {76AAF296-23B4-43de-8107-7381DEADD769}
static const IID IID_ICalc =
{ 0x76aaf296, 0x23b4, 0x43de, { 0x81, 0x7, 0x73, 0x81, 0xde, 0xad, 0xd7, 0x69 } };
// Com 자체에도 ID를 부여한다.
// {026E86AC-95FA-4166-B77E-764BFAE33D4C}
static const CLSID CLSID_AnyCall = // class ID
{ 0x26e86ac, 0x95fa, 0x4166, { 0xb7, 0x7e, 0x76, 0x4b, 0xfa, 0xe3, 0x3d, 0x4c } };
#endif // _IFACE_H
2. AnyCall.h ( 인터페이스를 제공한다. )
more..
#ifndef _ANYCALL_H
#define _ANYCALL_H #include "IFACE.h"
#include <iostream>
using namespace std;
class AnyCall : public IPhone, public ICalc
{
LONG m_ref;
public:
AnyCall() : m_ref(0) { cout << "Created AnyCall" << endl; }
~AnyCall() { cout << "Destroyed AnyCall" << endl; }
virtual void Calling( char* number );
virtual int Plus( int a, int b );
virtual int Minus( int a, int b );
// 결국 모든 인터페이스는 IUnknown의 자식이므로
// 모든 COM에는 아래 3개의 함수가 들어 있어야 한다.
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual HRESULT __stdcall QueryInterface( const IID& iid, void** p );
};
// 객체 생성을 클라이언트가 직접 할 경우에는 반드시 AnyCall.h 가 전달되어야 한다.
// 즉, COM 이 변경되면 Client 도 다시 빌드해야 한다. - COM이 스스로의 객체를 만들어
// 줄 수 있어야 한다.
// 내부적으로 이미 선언되어 있다.
/*
#ifdef DLLSOURCE
#define DLLAPI _declspec(dllexport)
#else
#define DLLAPI _declspec(dllimport)
#endif
extern "C" DLLAPI IPhone* CreateInstance();
*/
#endif // _ANYCALL_H
#define _ANYCALL_H #include "IFACE.h"
#include <iostream>
using namespace std;
class AnyCall : public IPhone, public ICalc
{
LONG m_ref;
public:
AnyCall() : m_ref(0) { cout << "Created AnyCall" << endl; }
~AnyCall() { cout << "Destroyed AnyCall" << endl; }
virtual void Calling( char* number );
virtual int Plus( int a, int b );
virtual int Minus( int a, int b );
// 결국 모든 인터페이스는 IUnknown의 자식이므로
// 모든 COM에는 아래 3개의 함수가 들어 있어야 한다.
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual HRESULT __stdcall QueryInterface( const IID& iid, void** p );
};
// 객체 생성을 클라이언트가 직접 할 경우에는 반드시 AnyCall.h 가 전달되어야 한다.
// 즉, COM 이 변경되면 Client 도 다시 빌드해야 한다. - COM이 스스로의 객체를 만들어
// 줄 수 있어야 한다.
// 내부적으로 이미 선언되어 있다.
/*
#ifdef DLLSOURCE
#define DLLAPI _declspec(dllexport)
#else
#define DLLAPI _declspec(dllimport)
#endif
extern "C" DLLAPI IPhone* CreateInstance();
*/
#endif // _ANYCALL_H
3. AnyCall.cpp ( IUnknown 의 3개의 가상함수를 구현하고 기능을 구현해준다. )
more..
#define DLLSOURCE
#include "AnyCall.h"
#include "Registry.h"
void AnyCall::Calling( char* number )
{
cout << "Calling with Anycall - " << number << endl;
}
int AnyCall::Plus( int a, int b )
{
return a + b;
}
int AnyCall::Minus( int a, int b )
{
return a - b;
}
ULONG __stdcall AnyCall::AddRef()
{
return InterlockedIncrement( &m_ref );
}
ULONG __stdcall AnyCall::Release()
{
if( InterlockedDecrement( &m_ref ) == 0 )
{
delete this;
return 0;
}
return m_ref;
}
// 하나의 인터페이스를 사용 다른 인터페이스를 얻기 위해 호출하는 함수
HRESULT __stdcall AnyCall::QueryInterface( const IID& iid, void** ppv )
{
if( iid == IID_IUnknown ) // operator==(IID&, IID&) 가 미리 구현되어 있다.
{
// IPhone으로 해줘도 된다. 멤버 data가 없다.
*ppv = static_cast<IPhone*>(this);
}
else if( iid == IID_IPhone )
{
*ppv = static_cast<IPhone*>(this);
}
else if( iid == IID_ICalc )
{
*ppv = static_cast<ICalc*>(this);
}
else
{
// 지원하지 않은 인터페이스를 요청 했다.
*ppv = 0;
return E_NOINTERFACE;
}
static_cast<IPhone*>(*ppv)->AddRef();
return S_OK;
}
/* 무조건 IPhone 만 리턴하므로 원하는것을 리턴받아야 한다.
IPhone* CreateInstance()
{
IPhone* p = new AnyCall;
p->AddRef();
return p;
}
*/
static HMODULE g_hModule = NULL ;
const int CLSID_STRING_SIZE = 39;
const char szFriendlyName[] = "AnyCall Example";
const char szVerIndProgID[] = "AnyCall.Control";
const char szProgID[] = "AnyCall.Control.1";
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
g_hModule = hModule;
break;
}
return TRUE;
}
// CreateInstance를 대체할 함수..
// #define STDAPI extern "C" HRESULT __stdcall
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
//if( clsid == CLSID_AnyCall ) 라면 객체생성을 한다.
AnyCall* p = new AnyCall;
if ( iid == IID_IUnknown )
{
*ppv = static_cast<IPhone*>(p);
}
else if ( iid == IID_IPhone )
{
*ppv = static_cast<IPhone*>(p);
}
else if ( iid == IID_ICalc )
{
*ppv = static_cast<ICalc*>(p);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
STDAPI DllRegisterServer()
{
// Get server location.
char szCLSID[CLSID_STRING_SIZE];
char szModule[512] ;
char szKey[64] ;
DWORD dwResult = ::GetModuleFileName(
g_hModule,
szModule,
sizeof(szModule)/sizeof(char)) ;
if(dwResult == 0)
return E_FAIL;
// CLSID\{504966F2-40AB-4bff-916A-15E3E91424B3}키를 조합하기 위한 루틴
ClsidToChar(CLSID_AnyCall, szCLSID, sizeof(szCLSID));
strcpy(szKey, "CLSID") ;
strcat(szKey, szCLSID) ;
SetRegistryInform(szKey, NULL, szFriendlyName);
SetRegistryInform(szKey, "InprocServer32", szModule);
SetRegistryInform(szKey, "ProgID", szProgID);
SetRegistryInform(szKey, "VersionIndependentProgID",szVerIndProgID) ;
// HKEY_CLASSES_ROOT\LittleSum Example
SetRegistryInform(szVerIndProgID, NULL, szFriendlyName) ;
SetRegistryInform(szVerIndProgID, "CLSID", szCLSID) ;
SetRegistryInform(szVerIndProgID, "CurVer", szProgID) ;
// HKEY_CLASSES_ROOT\LittleSum.Control.1
SetRegistryInform(szProgID, NULL, szFriendlyName) ;
SetRegistryInform(szProgID, "CLSID\\", szCLSID) ;
return S_OK ;
}
STDAPI DllUnregisterServer()
{
// Build the key CLSID\\{...}
char szCLSID[CLSID_STRING_SIZE];
char szKey[64] ;
ClsidToChar(CLSID_AnyCall, szCLSID, sizeof(szCLSID));
strcpy(szKey, "CLSID\\") ;
strcat(szKey, szCLSID) ;
// CLSID Key - CLSID\{...} 삭제.
LONG lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szKey) ;
// version-independent ProgID Key 삭제.
lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
// ProgID key 삭제.
lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szProgID) ;
return S_OK ;
}
#include "AnyCall.h"
#include "Registry.h"
void AnyCall::Calling( char* number )
{
cout << "Calling with Anycall - " << number << endl;
}
int AnyCall::Plus( int a, int b )
{
return a + b;
}
int AnyCall::Minus( int a, int b )
{
return a - b;
}
ULONG __stdcall AnyCall::AddRef()
{
return InterlockedIncrement( &m_ref );
}
ULONG __stdcall AnyCall::Release()
{
if( InterlockedDecrement( &m_ref ) == 0 )
{
delete this;
return 0;
}
return m_ref;
}
// 하나의 인터페이스를 사용 다른 인터페이스를 얻기 위해 호출하는 함수
HRESULT __stdcall AnyCall::QueryInterface( const IID& iid, void** ppv )
{
if( iid == IID_IUnknown ) // operator==(IID&, IID&) 가 미리 구현되어 있다.
{
// IPhone으로 해줘도 된다. 멤버 data가 없다.
*ppv = static_cast<IPhone*>(this);
}
else if( iid == IID_IPhone )
{
*ppv = static_cast<IPhone*>(this);
}
else if( iid == IID_ICalc )
{
*ppv = static_cast<ICalc*>(this);
}
else
{
// 지원하지 않은 인터페이스를 요청 했다.
*ppv = 0;
return E_NOINTERFACE;
}
static_cast<IPhone*>(*ppv)->AddRef();
return S_OK;
}
/* 무조건 IPhone 만 리턴하므로 원하는것을 리턴받아야 한다.
IPhone* CreateInstance()
{
IPhone* p = new AnyCall;
p->AddRef();
return p;
}
*/
static HMODULE g_hModule = NULL ;
const int CLSID_STRING_SIZE = 39;
const char szFriendlyName[] = "AnyCall Example";
const char szVerIndProgID[] = "AnyCall.Control";
const char szProgID[] = "AnyCall.Control.1";
BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
g_hModule = hModule;
break;
}
return TRUE;
}
// CreateInstance를 대체할 함수..
// #define STDAPI extern "C" HRESULT __stdcall
STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
//if( clsid == CLSID_AnyCall ) 라면 객체생성을 한다.
AnyCall* p = new AnyCall;
if ( iid == IID_IUnknown )
{
*ppv = static_cast<IPhone*>(p);
}
else if ( iid == IID_IPhone )
{
*ppv = static_cast<IPhone*>(p);
}
else if ( iid == IID_ICalc )
{
*ppv = static_cast<ICalc*>(p);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
STDAPI DllRegisterServer()
{
// Get server location.
char szCLSID[CLSID_STRING_SIZE];
char szModule[512] ;
char szKey[64] ;
DWORD dwResult = ::GetModuleFileName(
g_hModule,
szModule,
sizeof(szModule)/sizeof(char)) ;
if(dwResult == 0)
return E_FAIL;
// CLSID\{504966F2-40AB-4bff-916A-15E3E91424B3}키를 조합하기 위한 루틴
ClsidToChar(CLSID_AnyCall, szCLSID, sizeof(szCLSID));
strcpy(szKey, "CLSID") ;
strcat(szKey, szCLSID) ;
SetRegistryInform(szKey, NULL, szFriendlyName);
SetRegistryInform(szKey, "InprocServer32", szModule);
SetRegistryInform(szKey, "ProgID", szProgID);
SetRegistryInform(szKey, "VersionIndependentProgID",szVerIndProgID) ;
// HKEY_CLASSES_ROOT\LittleSum Example
SetRegistryInform(szVerIndProgID, NULL, szFriendlyName) ;
SetRegistryInform(szVerIndProgID, "CLSID", szCLSID) ;
SetRegistryInform(szVerIndProgID, "CurVer", szProgID) ;
// HKEY_CLASSES_ROOT\LittleSum.Control.1
SetRegistryInform(szProgID, NULL, szFriendlyName) ;
SetRegistryInform(szProgID, "CLSID\\", szCLSID) ;
return S_OK ;
}
STDAPI DllUnregisterServer()
{
// Build the key CLSID\\{...}
char szCLSID[CLSID_STRING_SIZE];
char szKey[64] ;
ClsidToChar(CLSID_AnyCall, szCLSID, sizeof(szCLSID));
strcpy(szKey, "CLSID\\") ;
strcat(szKey, szCLSID) ;
// CLSID Key - CLSID\{...} 삭제.
LONG lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szKey) ;
// version-independent ProgID Key 삭제.
lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
// ProgID key 삭제.
lResult = DeleteRegistryKey(HKEY_CLASSES_ROOT, szProgID) ;
return S_OK ;
}
4. Registry.h( 레지스트리 함수를 제공한다. )
more..
#ifndef __Registry_H__
#define __Registry_H__ void ClsidToChar(const CLSID& clsid, char* szCLSID, int length);
BOOL SetRegistryInform(const char* szKey, const char* szSubkey, const char* szValue);
DWORD DeleteRegistryKey(HKEY hStartKey , const char* pKeyName );
#endif
#define __Registry_H__ void ClsidToChar(const CLSID& clsid, char* szCLSID, int length);
BOOL SetRegistryInform(const char* szKey, const char* szSubkey, const char* szValue);
DWORD DeleteRegistryKey(HKEY hStartKey , const char* pKeyName );
#endif
5. Registry.cpp( 레지스트리 함수를 제공한다. )
more..
#undef UNICODE
#undef _UNICODE
#include <windows.h>
#include "registry.h"
// CLSID 를 문자열로 변경해 준다.
void ClsidToChar(const CLSID& clsid, char* szCLSID, int length)
{
LPOLESTR wszCLSID = NULL ;
HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
wcstombs(szCLSID, wszCLSID, length) ;
CoTaskMemFree(wszCLSID) ;
}
BOOL SetRegistryInform(const char* szKey, const char* szSubkey, const char* szValue)
{
HKEY hKey;
char szBuf[1024] ;
// 레지스터리의 키 와 서버 키의 값을 szBuf에 기록한다.
strcpy(szBuf, szKey) ;
if (szSubkey != NULL)
{
strcat(szBuf, "") ;
strcat(szBuf, szSubkey ) ;
}
// szBuf에 기록된 키 값의 정보를 가지고 키를 생성한다.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT,
szBuf,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL,
&hKey,
NULL) ;
if (lResult != ERROR_SUCCESS)
{
return FALSE ;
}
RegSetValueEx(hKey,
NULL,
0,
REG_SZ,
(BYTE *)szValue,
strlen(szValue)+1) ;
RegCloseKey(hKey) ;
return TRUE ;
}
DWORD DeleteRegistryKey(HKEY hStartKey , const char* pKeyName )
{
DWORD dwRtn, dwSubKeyLength;
LPTSTR pSubKey = NULL;
TCHAR szSubKey[256];
HKEY hKey;
// NULL 값 혹은 pKeyName에 정보가 없다면 리턴한다.
if ( pKeyName && lstrlen(pKeyName))
{
if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName,
0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey )) == ERROR_SUCCESS)
{
while (dwRtn == ERROR_SUCCESS )
{
dwSubKeyLength = 256;
dwRtn=RegEnumKeyEx(
hKey,
0, // always index zero
szSubKey,
&dwSubKeyLength,
NULL,
NULL,
NULL,
NULL
);
if(dwRtn == ERROR_NO_MORE_ITEMS)
{
dwRtn = RegDeleteKey(hStartKey, pKeyName);
break;
}
else if(dwRtn == ERROR_SUCCESS)
dwRtn=DeleteRegistryKey(hKey, szSubKey);
}
RegCloseKey(hKey);
}
}
else
dwRtn = ERROR_BADKEY;
return dwRtn;
}
#undef _UNICODE
#include <windows.h>
#include "registry.h"
// CLSID 를 문자열로 변경해 준다.
void ClsidToChar(const CLSID& clsid, char* szCLSID, int length)
{
LPOLESTR wszCLSID = NULL ;
HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
wcstombs(szCLSID, wszCLSID, length) ;
CoTaskMemFree(wszCLSID) ;
}
BOOL SetRegistryInform(const char* szKey, const char* szSubkey, const char* szValue)
{
HKEY hKey;
char szBuf[1024] ;
// 레지스터리의 키 와 서버 키의 값을 szBuf에 기록한다.
strcpy(szBuf, szKey) ;
if (szSubkey != NULL)
{
strcat(szBuf, "") ;
strcat(szBuf, szSubkey ) ;
}
// szBuf에 기록된 키 값의 정보를 가지고 키를 생성한다.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT,
szBuf,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL,
&hKey,
NULL) ;
if (lResult != ERROR_SUCCESS)
{
return FALSE ;
}
RegSetValueEx(hKey,
NULL,
0,
REG_SZ,
(BYTE *)szValue,
strlen(szValue)+1) ;
RegCloseKey(hKey) ;
return TRUE ;
}
DWORD DeleteRegistryKey(HKEY hStartKey , const char* pKeyName )
{
DWORD dwRtn, dwSubKeyLength;
LPTSTR pSubKey = NULL;
TCHAR szSubKey[256];
HKEY hKey;
// NULL 값 혹은 pKeyName에 정보가 없다면 리턴한다.
if ( pKeyName && lstrlen(pKeyName))
{
if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName,
0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey )) == ERROR_SUCCESS)
{
while (dwRtn == ERROR_SUCCESS )
{
dwSubKeyLength = 256;
dwRtn=RegEnumKeyEx(
hKey,
0, // always index zero
szSubKey,
&dwSubKeyLength,
NULL,
NULL,
NULL,
NULL
);
if(dwRtn == ERROR_NO_MORE_ITEMS)
{
dwRtn = RegDeleteKey(hStartKey, pKeyName);
break;
}
else if(dwRtn == ERROR_SUCCESS)
dwRtn=DeleteRegistryKey(hKey, szSubKey);
}
RegCloseKey(hKey);
}
}
else
dwRtn = ERROR_BADKEY;
return dwRtn;
}
6. Anycall.def ( dllexport 역할을 해준다. )
more..
LIBRARY Com.dll
EXPORTS
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
1. UseCom ( Com 을 사용하는 방법 - dll로드가 아닌 레지스트리에 등록된 COM을 사용한다. )
more..
#undef _UNICODE
#undef UNICODE
#include <iostream>
#include <windows.h>
#include "../Com/IFace.h" // 인터페이스를 제공하는 헤더파일.
using namespace std;
typedef IPhone*(*CREATEINSTANCE)();
int main()
{
CoInitialize(0); // COM 라이브러리 초기화
IPhone* phone = 0;
// 레지스트리에 가서 CLSID를 찾은 후에 해당 DLL을 load하고
// DllGetClassObject 함수를 찾은 후에 호출해서 객체를 만든다.
HRESULT ret = CoGetClassObject( CLSID_AnyCall, // COM의 CLSID
CLSCTX_INPROC_SERVER, // DLL에 있다.
NULL, // 통합(NULL 사용안함)
IID_IPhone, // 원하는 인터페이스 ID
(void**)&phone); // 인터페이스를 담을 포인터.
if ( FAILED(ret ) )
{
cout << "Error" << endl;
return 0;
}
phone->Calling("010-111-2222");
ICalc* pCalc = 0;
ret = phone->QueryInterface( IID_ICalc, (void**)&pCalc);
cout << pCalc->Plus(1,2) << endl;
pCalc->Release();
phone->Release();
CoUninitialize(); // 초기화 해제.
}
#undef UNICODE
#include <iostream>
#include <windows.h>
#include "../Com/IFace.h" // 인터페이스를 제공하는 헤더파일.
using namespace std;
typedef IPhone*(*CREATEINSTANCE)();
int main()
{
CoInitialize(0); // COM 라이브러리 초기화
IPhone* phone = 0;
// 레지스트리에 가서 CLSID를 찾은 후에 해당 DLL을 load하고
// DllGetClassObject 함수를 찾은 후에 호출해서 객체를 만든다.
HRESULT ret = CoGetClassObject( CLSID_AnyCall, // COM의 CLSID
CLSCTX_INPROC_SERVER, // DLL에 있다.
NULL, // 통합(NULL 사용안함)
IID_IPhone, // 원하는 인터페이스 ID
(void**)&phone); // 인터페이스를 담을 포인터.
if ( FAILED(ret ) )
{
cout << "Error" << endl;
return 0;
}
phone->Calling("010-111-2222");
ICalc* pCalc = 0;
ret = phone->QueryInterface( IID_ICalc, (void**)&pCalc);
cout << pCalc->Plus(1,2) << endl;
pCalc->Release();
phone->Release();
CoUninitialize(); // 초기화 해제.
}



댓글을 달아 주세요
어떤 자료파일(예하면 텍스트파일)을 더블클릭으로 내가 만든 편집기에서 나오게 하려면 어떻게 해야 하나요?
음. 텍스트 파일을 원하는 프로그램으로 열려면 해당 파일에서 우클릭해서 메뉴를 띠운다
음에 연결프로그램에서 원하는 편집기를 선택하면(항상이프로그램으로 열기) 될 거예요.
연결프로그램이 안뜨면 Shift+우클릭해서 해보고요~.
아 혹시 저런 방법 말고 프로그램으로 바꾸려면 (HKEY_CLASSES_ROOT\.txt)
레지스트리를 수정해서 해야는데 Registry 클래스를 이용해보세요.
내 프로그램에서는 다른 조작을 해줄게 없나요?
프로그램 시작인자로 화일경로를 받아서 열어주면 될거에요.
예전에 당근 프로젝트 분석해봐는데 그게 많이 도움이 될더라고요. 참고하세요.
http://winapi.co.kr/project/dangeun/dgintro.htm
알려주어 고마워요