본문 바로가기
컴퓨터 활용(한글, 오피스 등)/50_1. 운영체제_윈도우

윈도우_코드_COM

by 3604 2022. 10. 20.
728x90

 

Type Libraries(.TLB) 파일을 레지스트리에 등록하는 방법입니다.

출처: https://docko.tistory.com/169 [프로그래머의 꿈:티스토리]

아래의 명령어를 도스창 또는 윈도우즈의 실행에서 수행하시면 됩니다.

 

 C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe  TypeLibrariesFile.tlb

 

 

 

 

전병선의 Component Development with Visual C++ & ATL(27) – Visual C++ COM 컴파일러(1) – 개요, 타입라이브러리

http://youmin3.egloos.com/1636146

1.         Visual C++ COM 컴파일러

1.1.        COM 지원 C++ 컴파일러 개요

Visual C++ 컴파일러는 COM 컴포넌트의 형식 라이브러리(type library)를 직접 읽어, 그것을 컴파일 가능한 C++ 소스 코드로 변환하는 기능을 제공한다.

이와 함께 Visual C++ 컴파일러는 COM을 지원하기 위한 C++ 언어 확장 예약어와 클래스를 제공한다.

Visual C++은 이와 같은 COM 지원 기능으로 인해, 이제 개발자들은 우리가 지금까지 살펴본 바와 같은 복잡한 코드를 작성하지 않아도 손쉽게 COM 클라이언트 애플리케이션을 구현할 수 있게 되었다.

 

Visual C++ 컴파일러는 COM을 지원하기 위해 다음과 같은 예약어와 클래스를 추가로 지원한다.

l        #import 선행 차리기 지시어

l        __declspec 확장속성: uuid  property

l        __uuidof

l        _com_ptr_t 클래스

l        _com_error

l        _bstr_t 클래스

l        _variant_t 클래스

l        전역 함수

 

 

1.1.1.       예약어와 클래스를 사용하여 COM 클라이언트 어플리케이션을 작성 예.

 

다음은 2 COM 컴포넌트 사용에서 구현했던 HelloClient 어플리케이션과 동일한 기능을 이들 예약어와 클래스를 사용하여 작성된 코드의 예를 보여준다.

 

#import "progid:HelloServer.Hello.1" no_namespace
 
        try {
             IHelloPtr pIHello(__uuidof(Hello));
               wchar_t* message = NULL;
               wchar_t* name;
               char buffer[256];
               cout << "이름을입력하세요: ";
               cin >> buffer;
               name = (wchar_t*)buffer;
             pIHello->sayHello(name, &message);
 
               cout << (char*)message << endl;
              
               ::CoTaskMemFree((LPVOID)message);
        }
       catch(_com_error& e) {
             cout << e.ErrorMessage() << endl;
       }

 

위의 코드에서 굵은체로 표시된 코드의 부분이 COM 컴포넌트를 사용하기 위해 작성해야 하는 코드이다.

위의 코드에서는 COM 객체의 CLSID를 구하기 위한 코드가 없다.

그저 #import 선행 처리기 지시어를 사용하여 사용하고자 하는 COM 객체의 프로그램ID만 지정하면 된다.

 

#import "progid:HelloServer.Hello.1" no_namespace

 

따라서 #import 선행 처리기 지시어를 사용하면 다음과 같이 CLSIDFromProgID()를 사용할 필요가 없어진다.

 

CLSID clsid;
hr = ::CLSIDFromProgID(L"HelloServer.Hello.1", &clsid);

 

 

1.1.2.       COM 객체 인스턴스를 생성하는 코드

 

IHelloPtr pIHello(__uuidof(Hello));

 

위의 코드는 다음 코드를 한 문장으로 함축적으로 표현하고 있다.

 

IUnknown* pUnk = NULL;
IHello* pIHello = NULL;
hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL,
                       IID_IUnknown, (void**)&pUnk);
pUnk->QueryInterface(IID_IHello, (void**)&pIHello);

 

 

COM 객체의 인터페이스를 사용하기 위해 IUnknown 인터페이스의 AddRef() Release()에 신경 쓸 필요가 없다. 그냥 인터페이스 포인터를 통해 서비스를 사용하고 내버려두어도 된다.

 

pIHello->sayHello(name, &message);
// pIHello->Release()를호출할필요가없다.

 

 

1.1.3.       COM 관현 함수나, 인터페이스 메서드를 호출하고 HRESULT 리턴 값을 체크할 필요가 없다. 그저 try/catch 구문을 사용하여 일괄적으로 com_error& 타입의 예외를 잡기만 하면 된다.

 

try
{
        // ...
}
catch (_com_error& e)
{
        cout << e->ErrorMessage() << endl
}

 

따라서 더 이상 다음과 같은 코드를 일일이 작성해야 할 필요가 없어진다.

 

HRESULT hr;
hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL,
                       IID_IUnknown, (void**)&pUnk);
if (hr != S_OK)
{
        cout << "인스턴스를생성할수없습니다!" << endl;
        return 0;
}

 

 

 

1.2.        형식 라이브러리(type library)

앞에서 COM 객체 또는 COM 객체가 노출하는 인터페이스에 대한 정보를 COM 객체에서 제공하는 소스 코드에 의존하였다. 따라서, 만약 COM 객체가 자신에 대한 정보를 소스 코드 형태로 제공하지 않는다면 결국 우리는 해당 COM 객체를 사용할 수 없게 될 것이다.

이것은 이진(binary) 형태로만 제공되는 대부분의 COM 컴포넌트에서는 문제가 된다. COM은 이러한 문제점을 형식 라이브러리(type library)를 사용함으로써 해결한다.

, COM 객체는 소스 코드 대신에 형식 라이브러리를 제공함으로써 COM 클라이언트 어플리케이션에게 COM 객체에 대한 정보를 제공해 줄 수 있게 된다.

 

형식 라이브러리(type library) COM 컴포넌트가 노출하는 COM 객체에 대한 정보를 포함하고 있는 .TLB 확장자를 갖는 일종의 복합 다큐먼트(compound document)이다.

우리는 형식 라이브러리를 COM 객체에 대한 일종의 매뉴얼이라고 생각할 수 있다. COM 컴포넌트가 형식 라이브러리를 제공하기 위해서는 다음과 같이 IDL 파일에 형식 라이브러리 정보를 지정해야 한다.

 

import "oaidl.idl";
import "ocidl.idl";
 
[
        object,
        uuid(C4646F65-6C21-4051-8DA8-E0AC06BF1CEB),
        helpstring("IHello 인터페이스"),
        pointer_default(unique)
]
interface IHello : IUnknown {
        [helpstring("메서드sayHello")]
        HRESULT  sayHello([in] wchar_t *name, [out] wchar_t **message );
};
[
       uuid(c3c0047a-5622-33c1-bbcb-01cbbb054f5a) ,
       version(1.0),
       helpstring("HelloServer 1.0 형식라이브러리")
]
library HelloServerLib
{
       importlib("stdole2.tlb");
       [
             uuid(D84CDA2F-5AF1-4e97-BE21-983E0AB93D67),
             helpstring("Hello Class")
       ]
       coclass CHello {
             [default] interface IHello;
       };
};

 

위의 코드에서 굵은체 부분이 형식 라이브러리에 대한 IDL 구문이다. (형식 라이브러리의 IDL 구문은, 우리가 ATL을 사용하여 COM 컴포넌트를 구현할 때 ATL 마법사들이 자동적으로 형식 라이브러리 구문을 제공하게 된다)

 

MIDL 컴파일러는 이 IDL 구문을 컴파일하여 .TLB 확장자를 갖는 파일을 생성하여 형식 라이브러리에 저장한다. (MIDL 컴파일러는 IDL에 정의된 인터페이스에 대한 C++ 인터페이스 클래스를 생성하며, 아웃-오브-프로세스 서버 컴포넌트의 커스텀 인터페이스에 대한 마샬링 기능을 제공하는 프록시/스텁 코드를 생성하고, COM 컴포넌트가 제공하는 COM 객체와 인터페이스에 대한 정보를 포함하는 형식 라이브러리를 생성하는 기능을 제공한다.

 

이때, 형식 라이브러리는 DLL이나 EXE 파일에 리소스로 포함될 수 있다.

이때 리소스 스크립트 파일(.rc)에는 다음과 같이 선언된다.

 

1       TYPELIB "HelloServer.tlb"

 

그 밖에도 복합 다큐먼트(compound document)나 기타 LoadTypeLib API 함수가 인식할 수 있는 파일 형식 안에 형식 라이브러리가 포함될 수 있다.

형식 라이브러리 자체도 ITypeLib, ITypeLib2, ITypeInfo, ITypeInfo2, ITypeComp 인터페이스를 노출하는 하나의 COM 객체이므로 Visual C++ 컴파일러나 OLE/COM 객체 뷰어와 같은 툴은 이들 인터페이스를 통하여 형식 라이브러리가 제공하는 정보에 접근할 수 있다.

또한, MIDL 컴파일러는 ICreateTypeLib, ICreateTypeLib2, ICreateTypeInfo, ICreateTypeInfo2 인터페이스를 사용하여 형식 라이브러리를 생성하게 된다.

형식 라이브러리의 정보는 레지스트리의 HKEY_CLASSES_ROOT\TypeLib 서브키에 저장된다.

728x90