com 개체 구현 실습 addback local server 예제 프로그램 작성. 2 addback local server...

22
COM 개개 개개 개개 AddBack Local Server 개개 개개개개 개개

Upload: claude-knight

Post on 17-Dec-2015

223 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

COM 개체 구현 실습

AddBack Local Server 예제 프로그램 작성

Page 2: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

2

AddBack Local Server 구현

1. Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택

2. [New] 대화 상자의 [Properties] 탭에서 [Win32 Application] 항목 선택

3. [Location] 텍스트 상자에 앞에서 생성한 AddBack 폴더를 지정

4. [Project] 텍스트 상자에 ‘ AddBack’ 이라고 입력5. [Location] 텍스트 상자 끝에 추가된 ‘ AddBack’ 을

‘OutProc’ 으로 변경6. [OK] 명령 단추를 클릭

Page 3: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

3

Page 4: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

4

7. 앞에서 생성한 AddEnd.cpp 와 Factory.cpp 파일을 OutProc 폴더에 복사한 후 , 두 파일을 AddBack 프로젝트에 추가

8. AddBack 프로젝트에 ‘ AddBack.cpp’ 파일을 생성하여 추가한다

9. AddBack.cpp 파일에 다음과 같은 6 개의 파일을 포함시킨다#include <windows.h>

#include <ole2.h>

#include "..\AddBack.h"

#include "..\Factory.h"

#include "..\Guid.h"

#include "..\Guid.cpp"

Page 5: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

5

10. WinMain 함수 구현HINSTANCE g_hInstance;DWORD g_dwRegister;CFAddBack* g_pFactory;

BOOL OpenFactory(void);BOOL CloseFactory(void);void RegisterServer (void);void UnregisterServer (void);BOOL SetRegKeyValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValue);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ // TODO: Place code here.

HRESULT hr;MSG msg;

hr = CoInitialize(NULL);if(FAILED(hr)) {

MessageBox(NULL, "COM 라이브러리를 초기화할 수 없습니다 !", NULL, MB_OK);

return 0;}

Page 6: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

6

// EXE 화일은 DllGetClassObject, DllCanUnloadNow, DllRegisterServer, // DllUnregisterServer 함수를 노출시키지 못한다 . // 명령행에서 WinMain 함수에 넘어온 매개변수의 값이 RegServer 또는 UnregServer 옵션을 // 포함하고 있는 지를 검사하여 레지스트리에 등록 또는 해제하는 함수를 호출

if (lstrcmpiA(lpCmdLine, "-RegServer") == 0 ||lstrcmpiA(lpCmdLine, "/RegServer") == 0) {

g_hInstance = hInstance; RegisterServer(); return 0;

}elseif (lstrcmpiA(lpCmdLine, "-UnregServer") == 0 ||

lstrcmpiA(lpCmdLine, "/UnregServer") == 0) { UnregisterServer(); return 0;

}

if (lstrcmpiA(lpCmdLine, "-Embedding") == 0 ||lstrcmpiA(lpCmdLine, "/Embedding") == 0)

OpenFactory();

while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);

}

CloseFactory();::CoUninitialize();

return 0;}

Page 7: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

7

11.ROT(Running Object Table) 에 클래스 팩토리 COM 개체를 등록하는 코드 구현BOOL OpenFactory(void) // CoGetClassObject 에서 호출{ // (ROT 참조후 없으면 호출 ) BOOL bOK = FALSE; HRESULT hr;

g_pFactory = new CFAddBack; if(g_pFactory != NULL) { g_pFactory->AddRef(); hr = ::CoRegisterClassObject(CLSID_AddBack, g_pFactory,

CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE,&g_dwRegister);

bOK = SUCCEEDED(hr); if(!bOK) { g_pFactory->Release(); delete g_pFactory; } } else bOK = FALSE;

return bOK;}

Page 8: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

8

BOOL CloseFactory(void){ BOOL bOK = TRUE; HRESULT hr;

if (g_dwRegister != 0) { hr = CoRevokeClassObject(g_dwRegister); if (FAILED(hr)) bOK = FALSE; } if(g_pFactory) g_pFactory->Release();

return bOK;}

Page 9: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

9

13.WinMain 함수 앞에 카운터로 사용할 전역 변수 정의HINSTANCE g_hInstance;DWORD g_dwRegister;CFAddBack* g_pFactory;LONG g_cObjects = 0; // COM 개체 카운터LONG g_cLocks = 0; // 로크 카운터

BOOL OpenFactory(void);BOOL CloseFactory(void);void RegisterServer (void);void UnregisterServer (void);BOOL SetRegKeyValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValue);

int APIENTRY WinMain(HINSTANCE hInstance,

14.AddBack 프로젝트에 ‘ Add.h’ 헤더 파일을 생성하고 앞에서 정의한 전역 변수 선언

extern LONG g_cObjects;

extern LONG g_cLocks;

void CloseExe (void);

Page 10: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

10

15.CFAddBack::CreateInstance 메소드에 COM 개체 카운터를 반영하는 코드 추가HRESULT __stdcall CFAddBack::CreateInstance(LPUNKNOWN pUnkOuter,

REFIID riid, LPVOID* ppv){ HRESULT hr = E_FAIL; CAddBack* pAddBack = NULL; *ppv = NULL;

if(pUnkOuter != NULL) hr = CLASS_E_NOAGGREGATION; else { pAddBack = new CAddBack; if(pAddBack != NULL) { ++g_cObjects; // COM 개체 카운터를 증가시킨다 . // 클라이언트에서 요청한 인터페이스 포인터를 // CAddBack COM 개체에게 요청한다 . hr = pAddBack->QueryInterface(riid, ppv); if(FAILED(hr)) { --g_cObjects; // 실패한 경우 COM 개체 카운터를 감소시킨다 . delete pAddBack; CloseExe(); // 가능하다면 종료한다 . } } else hr = E_OUTOFMEMORY; } return hr;}

Page 11: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

11

16.CFAddBack::LockServer 메소드에 Lock Counter를 반영하는 코드 추가HRESULT __stdcall CFAddBack::LockServer(BOOL bLock){ if(bLock) ++g_cLocks; else --g_cLocks;

return S_OK;}

17.AddEnd.cpp 파일에 Add.h 헤더 파일을 포함시킨다

#include "..\AddEnd.h"#include "Add.h"

#include "..\AddBack_i.c"

Page 12: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

12

18. CAddBack::Release 메소드에 COM 개체 카운터를 반영하는 코드를 추가ULONG __stdcall CAddBack::Release(void)

{

if(--m_cRef == 0) {

// COM 개체 카운터를 감소시킨다 .

--g_cObjects;

delete this;

// 가능하다면 종료한다 .

CloseExe();

}

return m_cRef;

}

19. CloseExe 함수를 구현void CloseExe (void)

{

if (g_cObjects == 0 && g_cLocks == 0)

PostQuitMessage(0);

}

Page 13: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

13

20.AddBack COM 컴포넌트를 레지스트리에 등록 및 해제하는 RegisterServer 와 UnregisterServer 함수 구현void RegisterServer (void){ TCHAR szID[129]; TCHAR szCLSID[129]; TCHAR szModulePath[MAX_PATH]; wchar_t wszCLSID[129];

GetModuleFileName(g_hInstance, szModulePath, sizeof(szModulePath)/sizeof(TCHAR)); StringFromGUID2(CLSID_AddBack, wszCLSID, 128); wcstombs(szID, wszCLSID, 128) ;

lstrcpy(szCLSID, TEXT("CLSID\\")); lstrcat(szCLSID, szID); SetRegKeyValue(TEXT("AddBack.AddBack.1"), NULL, TEXT("AddBack Component")); SetRegKeyValue(TEXT("AddBack.AddBack.1"), TEXT("CLSID"), szID);

SetRegKeyValue(szCLSID, NULL, TEXT("AddBack Component")); SetRegKeyValue(szCLSID, TEXT("ProgID"), TEXT("AddBack.AddBack.1")); // 인 -프로세스 서버와 다른 부분 SetRegKeyValue(szCLSID, TEXT("LocalServer32"), szModulePath);}

Page 14: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

14

void UnregisterServer (void){ TCHAR szID[129]; TCHAR szCLSID[129]; TCHAR szTemp[129]; wchar_t wszCLSID[129];

StringFromGUID2(CLSID_AddBack, wszCLSID, 128); wcstombs(szID, wszCLSID, 128) ;

lstrcpy(szCLSID, TEXT("CLSID\\")); lstrcat(szCLSID, szID);

RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AddBack.AddBack.1\\CLSID")); RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("AddBack.AddBack.1"));

// 인 - 프로세스 서버와 다른 부분 wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("LocalServer32")); RegDeleteKey(HKEY_CLASSES_ROOT, szTemp); wsprintf(szTemp, TEXT("%s\\%s"), szCLSID, TEXT("ProgID")); RegDeleteKey(HKEY_CLASSES_ROOT, szTemp); RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);}

Page 15: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

15

BOOL SetRegKeyValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValue){ BOOL bOk = FALSE; LONG ec; HKEY hKey; TCHAR szKey[256];

lstrcpy(szKey, pszKey);

if(NULL != pszSubkey) { lstrcat(szKey, TEXT("\\")); lstrcat(szKey, pszSubkey); }

ec = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, NULL,REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,NULL, &hKey, NULL);

if(ERROR_SUCCESS == ec) { if(NULL != pszValue) { ec = RegSetValueEx(hKey, NULL, 0, REG_SZ, (BYTE *)pszValue,

(lstrlen(pszValue)+1)*sizeof(TCHAR)); } if(ERROR_SUCCESS == ec) bOk = TRUE; RegCloseKey(hKey); }

return bOk;}

Page 16: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

16

21.AddBack 프로젝트를 build 하여 AddBack.exe 파일 생성

22.AddBack COM 컴포넌트를 레지스트리에 등록1. AddBack /regserver

2. 이것을 수행하기 위해서는 예전에 등록하였던 것을 해제하고 새로 등록해야 한다 .

23.AddFront 애플리케이션을 실행하여 AddBack COM 컴포넌트 실행 확인1. AddBack 컴포넌트를 생성할 수 없다는 에러 발생2. AddBack Local Server 에 인터페이스를 marshalling 하는

Proxy/Stub DLL 이 없기 때문

Page 17: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

17

Proxy/Stub DLL 생성

MIDL 컴파일러가 생성한 코드 사용1. Visual C++ 개발 환경의 [File/New] 메뉴 항목 선택2. [New] 대화 상자의 [Project] 탭에서 [Win32

Dynamic Link Library] 항목 선택3. [Location] 텍스트 상자에 앞에서 생성한 AddBack

폴더 지정4. [Project] 텍스트 상자에 ‘ Marshal’ 이라고 입력5. [Add to current workspace] 옵션 선택6. [OK] 버튼 클릭

Page 18: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

18

Page 19: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

19

7. MIDL 컴파일러가 생성한 AddBack_i.c, AddBack_p.c, 그리고 DllData.c 파일을 Marshal 프로젝트에 포함시킨다

Page 20: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

20

8. 프로젝트에 RPC runtime import library 를 추가하기 위해 [Project/Settings] 메뉴 항목을 선택하여 [Project Settings] 대화 상자의 [Link] 탭을 선택한 후 [Object/libraries modules] 텍스트 상자에 rpcrt4.lib 파일을 추가한다

Page 21: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

21

9. [Project Settings] 대화 상자 왼쪽의 트리뷰에서 DllData.c 항목을 선택하고 , 오른쪽 [C/C++] 탭에서 [Preprocessor definitions] 텍스트 상자에 ‘ REGISTER_PROXY_DLL’ 을 추가한다 . 이것은 생성된 Proxy/Stub 코드가 자기 등록을 할 수 있게 하기 위한 것이다 .

Page 22: COM 개체 구현 실습 AddBack Local Server 예제 프로그램 작성. 2 AddBack Local Server 구현 1.Visual C++ 개발 환경의 [File/New] 메뉴 항목을 선택 2.[New] 대화

22

10.Marshal 프로젝트에 ‘ Marshal.def’ 파일을 생성하여 추가

LIBRARY Marshal.dll

DESCRIPTION 'Proxy/Stub DLL'

EXPORTSDllGetClassObject@1 PRIVATEDllCanUnloadNow @2 PRIVATEGetProxyDllInfo @3 PRIVATEDllRegisterServer@4 PRIVATEDllUnregisterServer @5 PRIVATE

11.Marshal 프로젝트를 build 하여 Marshal.dll 파일을 생성

12.regsvr32.exe 를 사용하여 Proxy/Stub DLL COM 컴포넌트를 레지스트리에 등록1. regsvr32 Marshal.dll

13.AddFront 애플리케이션을 실행하여 AddBack COM 컴포넌트가 제대로 실행되는지 확인