.NET에서 네이티브 COM 서버 사용

업데이트: 2007년 11월

이 단원에서는 .NET 응용 프로그램에서 기존 COM 구성 요소를 사용하는 데 적용할 수 있는 옵션에 대해 설명하고 각 접근 방식에 따른 이점과 단점에 대해 간략하게 설명합니다. 일반적으로는 C++ Interop를 사용하는 것이 좋습니다.

TLBIMP 사용

Windows SDK(소프트웨어 개발 키트)형식 라이브러리 가져오기(Tlbimp.exe)는 COM 형식 라이브러리를 Interop 어셈블리라는 어셈블리로 노출하는 도구입니다. 이 어셈블리는 해당 형식 라이브러리에 있는 각 COM 인터페이스에 대해 동일한 기능의 관리되는 요소, 즉 래퍼를 정의합니다.

Interop 어셈블리의 메서드를 호출하면 관리되는 형식에서 관리되지 않는 형식으로 전환이 실행되고 컨트롤이 COM 구성 요소에 전달됩니다. 마찬가지로, 관리되지 않는 COM 함수가 반환할 때는 관리되지 않는 형식에서 관리되는 형식으로 전환이 실행됩니다. 기본적으로 COM HRESULT에서 오류가 있는지 확인하고 HRESULT가 실패한 경우 예외가 throw됩니다. 마찬가지로, COM 구성 요소 초기화 및 인터페이스 쿼리가 Interop 어셈블리를 통해 수행되므로 이는 호출 코드에서 숨겨집니다.

Interop 어셈블리는 이 어셈블리가 나타내는 COM 구성 요소를 대신하지 않습니다. 관리되지 않는 COM 함수는 COM 구성 요소에 남아 있으므로 이 구성 요소를 대상 컴퓨터에 설치하고 등록해야 합니다. 그렇지 않으면 Interop 어셈블리에 대한 호출이 실패합니다.

관리 코드에서 COM 구성 요소를 사용하는 가장 손쉬운 방법은 Tlbimp를 사용하는 것이지만, 이 경우 몇 가지 심각한 단점이 있으며 특히 COM 인터페이스가 크거나 복잡한 경우 다음과 같은 문제가 발생할 수 있습니다.

  • Tlbimp는 형식 라이브러리의 모든 COM 인터페이스에 대해 관리되는 인터페이스를 생성합니다. 이 동작을 해제하는 방법이 없으므로 결과 어셈블리가 매우 클 수 있습니다. 예를 들어, Mshtml.dll에 대해 Tlbimp로 생성된 Interop 어셈블리는 8MB를 넘습니다. COM 구성 요소 내에서만 사용하도록 지정된 인터페이스를 숨길 수 있는 방법도 없습니다.

  • Tlbimp가 지원하는 데이터 형식의 수는 제한되어 있습니다. 일반적으로 지원되지 않는 형식은 관리되는 환경에 형식이 안전하지 않은 제네릭 IntPtr 형식으로 가져오므로 어셈블리를 사용하기 위한 마샬링 코드가 필요하지만 이러한 코드는 오류가 발생하기 쉽고 복잡하며 때로는 Tlbimp.exe가 인터페이스의 멤버를 전혀 노출할 수 없는 경우가 있습니다.

  • Tlbimp는 최종 응용 프로그램과 함께 배포해야 하는 별도의 Interop 어셈블리를 생성합니다.

이러한 단점이 큰 문제가 되지 않는다면 방법: TLBIMP와 함께 네이티브 COM 서버 사용의 예제를 참조하십시오.

MSIL 수정

Tlbimp의 단점은 MSIL 디스어셈블러(Ildasm.exe)를 사용하여 Interop 어셈블리를 디스어셈블하고 불필요한 인터페이스 정의를 제거하고 인수 형식을 바꾸도록 MSIL을 편집한 다음 MSIL 어셈블러(Ilasm.exe)로 MSIL을 리어셈블하여 어느 정도 완화시킬 수 있습니다. 이 경우 오류가 발생할 가능성이 높으며 MSIL, 관리되지 않는 형식 및 .NET 형식에 대해 잘 알고 있어야 한다는 단점이 있습니다. 또한 COM 인터페이스가 업데이트되면 이 작업을 다시 수행해야 합니다.

C++ Interop

Visual C++에서는 Tlbimp를 사용하거나 MSIL을 편집하는 데 따른 단점이 전혀 발견되지 않습니다. Visual Basic이나 C#과는 달리 Visual C++에서는 CoCreateInstanceQueryInterface 같은 일반적인 COM 메커니즘을 통해 COM 개체를 직접 사용할 수 있기 때문입니다. C++ Interop를 사용하면 관리되는 함수에서 관리되지 않는 함수로 이동하고 다시 반대로 이동하는 전환 코드를 컴파일러에서 자동으로 삽입할 수 있습니다.

C++ Interop를 사용하면 C++ 클래스 내에서 래핑되거나 일반적으로 사용되는 것과 동일한 방식으로 COM 구성 요소를 사용할 수 있습니다. 이러한 래퍼 클래스를 사용자 지정 런타임 호출 가능 래퍼 또는 간단히 줄여 CRCW라 합니다. CRCW를 사용하면 응용 프로그램 코드에서 COM을 직접 사용하는 경우와 비교하여 두 가지 이점이 있습니다.

  • 결과 클래스를 Visual C++ 이외의 언어에서 사용할 수 있습니다.

  • COM 인터페이스의 세부 내용을 관리되는 클라이언트 코드에서 숨길 수 있습니다. 네이티브 형식 대신 .NET 데이터 형식을 사용할 수 있고 데이터 마샬링의 세부 내용을 CRCW 내에서 투명하게 수행할 수 있습니다.

Visual C++를 사용하여 COM 인터페이스를 래핑하는 예제는 방법: CRCW와 함께 네이티브 COM 서버 사용을 참조하십시오.

COM을 직접 사용하는지 CRCW를 통해 사용하는지 여부와 상관없이 단순한 blittable 형식 이외의 인수 형식은 모두 마샬링해야 합니다. 데이터 마샬링에 대한 자세한 내용은 C++ Interop 사용(암시적 PInvoke)을 참조하십시오.

참고:

MFC 응용 프로그램은 STA(Single Threaded Apartment)로 초기화해야 합니다. InitInstance 재정의에서 CoInitializeEx를 호출하는 경우 COINIT_MULTITHREADED 대신 COINIT_APARTMENTTHREADED를 지정합니다. 자세한 내용은 https://support.microsoft.com/default.aspx?scid=kb;en-us;828643에서 PRB: MFC Application Stops Responding When You Initialize the Application as a Multithreaded Apartment (828643)를 참조하십시오.

참고 항목

기타 리소스

네이티브 및 .NET 상호 운용성