본문 바로가기

3.구현/VC++

COM객체 regsvr32 등록시 DllRegisterServer실패 0x80000003에러

작성자: Ospace(ospace114@empal.com)
적성일: 08.01.10

프롤로그

COM객체를 작성하면서 짜증나는 부분이 COM객체 등록 부분이라 할 수 있다. 적어도 나는 그렇다. 특히 regsvr32에 의해서 COM객체 등록시 왜 이렇게 안되는 경우가 많은지, 어떤 에러인지 메시지만으로 알기 어려워서 더욱더 짜증나게 만든다.

여하튼 최근 DirectShow 필터를 작성해서 등록해서 잘 사용하고 있었다. 다시 필터 내부에 데이터 체크 부분을 보강하여 다시 빌드해서 사용하는데는 문제가 없었다.

이렇게 자주 COM 객체를 빌드해서 테스트 할때 regsvr32에 의해서 매번 해제와 등록 작업하는 것은 번거롭다. 그렇기에 한번 등록해두면 레지스트리에 해당 COM객체에 대한 절대위치 정보가 저장된다. 작업중인 COM객체의 절대위치에 COM 객체를 덮어쓰면 새로 빌드된 COM객체를 쉽게 테스트 할수 있다.

가끔 Debug와 Release로 빌드된 COM객체를 따로 구분하지 못하여 잘못된 위치의 COM객체로 디버깅하는 경우도 발생한다.

근데, 바로 이부분이 화근이 될줄이야.. 상황은 다음과 같다.

스토리

COM객체를 수정하고 테스트하고 이상이 없었다.

일단 기존 COM객체를 수정하려고 했는데 프로젝트 버전이 틀리다고 나온다. 기존 것은 VC 2005버전이고 지금 환경은 VC 2003이다. 이렇게 한 이유는 MFC 라이브러리 배포 문제 때문이다. 그래서 기존에 작성되었던 dsp혹은 dsw프로젝트를 열어서 새로운 sln 프로젝트를 생성해서 작업을 했다. 아무튼 릴리즈와 디버그 버전 테스트가 이상없이 끝났다.

COM객체 사용시 CO_E_ERRORINDL이라는 황당한 메시지

자체 설치 제거 테스트까지 끝나고 다시 작업을 들어가려고 COM객체를 등록하고 사용하던 중에 아래와 같은 에러가 발생했다.

CO_E_ERRORINDLL - 이에러는 객체 진입점을 찾을 수 없다는 메시지이다.

값자기 COM객체 잘 사용하던게 안되니깐 미치고 환장할 노릇이다. 다시 COM객체를 해제하고 등록까지 이상없이 끝낸후 다시 테스트 해도 마찬가지이다. 이 메시지는 IMoniter의 BindToObject메소드 호출시 발생했다.

디버그 빌드된 COM객체 등록시 황당한 ASSERT 메시지

갑자기 아무런 이유없이 에러가 발생하니 짜증이 엄청났다. 물론 아무런 이유가 없을리는 만무하다. 어찌되었든 소스코드 내부에 수정한게 문제가 있나 확인도 해보고, 빌드시 include나 라이브러리를 잘못 사용했나도 사용해보고, 혹시나 문자열 셋에 문제가 있나해서 유니코드로도 해보고 했다. 역시 마찬가지이다. 다시 디버깅을 해보기 위해서 디버깅 모드로 빌드하고 regsvr32로 등록 중에 다시 황당한 메시지가 발생했다. 으악!!! 미치기 일보직전이다.

등록된 COM 레지스트리 정보에 이상한 정보가 등록되었다.

한번 레지스트리 정보를 뒤지기 시작했다. COM객체가 등록된 경우 이상한 정보가 저장되었다. 보통 InprocServer32에 (기본값)에 해당 COM객체 절대위치정보가 저장되는데.. 떡하니 regsvr32.exe 자신이 등록되어 있는 것이다. ㅡ.ㅡㅋ

무식한 1대1로 프로젝트 빌드환경 비교하다.

그래서 판단하였다. 레지스트리에 잘못된 COM 정보가 등록되었고 이로 인해 정확한 COM객체에 접근하지 못하였기 때문에 진입접을 찾지못한다는 CO_E_ERRORINDLL이 발생했다고 판단했다. 그럼 COM 등록하는 절차를 다시 잘 접검하면 되겠다고 하여.. 위의 에러 메시지에 있는 DllRegisterServer를 찾고 이것 저것 봐도 전혀 이상이 없다. 결국 혹시 프로젝트 빌드환경에 문제가 있을 것라고 판단하여 기존 다른 COM객체 작성한 프로젝트 환경과 비교하였다.

유레카~

결국 Entry Point에 문제가 있다는 것을 찾아냈다. ㅠ.ㅠ
다음과 같이 Linker > Advanced에서 Entry Point를 DllEntryPoint@12로 해주면 된다. 이로 인해서 Regsvr32가 진입점을 찾지 못해서 발생했다는 것이다.

솔루션 탐색기(Solution Explorer)에 프로젝트를 선택하고 오른쪽 버전을 누르면 컨텍스트 메뉴가 나타납니다. 프로젝트의 속성(Properties)으로 들어가시면 Linker가 있습니다. Linker 밑에 Advanced를 선택하면 수정이 가능합니다.

이는 Visual Studio의 버전마다 조금 다를 수도 있지만, 기본 위치는 거의 비슷할 거라 생각됩니다.

정리

원인은 기존 프로젝트 파일을 사용해서이다.

이 문제를 발생시킨 가장 큰 원인은 프로젝트 파일 버전이 틀려서 기존 버전의 프로젝트 파일을 사용함에 있어서 문제가 발생했다. 컴파일과 링크 상에서 발생한 문제는 쉽게 확인하여 수정할 수 있으나 위와 같이 Entry Point에서 발생한 문제는 실제 실행하고 특정 조건에 만족하지 않는한 발생하지 않은다.

프로젝트 파일이 바뀜으로서 기존 환경설정이 변경되어 있고, 빌드작업시 발생하지 않은 잠재적인 문제점이 있었기 때문이다.

EntryPoint

진입점(EntryPoint)는 COM이 처음 호출되는 함수이라고 볼 수 있다. 특히 COM은 동적으로 로딩되는데 보통 DLL형태로 되어 있다. 이런 비슷한 형태로 Plugin 구조에서도 많이 볼 수 있다. 어쩌면 Plugin과 COM은 비슷하도고 볼 수도 있겠다.

이런 구조화된(?) 동적 라이브러리(DLL)를 로딩하면 자동으로 EntryPoint가 호출하게 된다. 물론 해제도 EntryPoint가 호출하게 된다. 즉, 로딩하면 EntryPoint에서 해당 라이브러리에 속한 COM 정보를 등록하거나 사용할 수 있는 형태로 만들어준다. 다른 말로 하면 해당 COM객체를 인스탄스(?)화하는 트리거 역활이라고 보면 된다.

결언

이에 대한 자료는 인터넷에서도 거의 발견할 수 없었다. 특히 0x80000003에 대한 에러코드는 E_INVALIDARG로 잘못된 인자로만 나오고 RegSvr32 관련해서 나오는 문제는 인터넷 상에서 거의 찾아 볼 수 없었다. 그리고 ASSERT에러에서 g_hInst 관련한 것은 아애 없다고 보면된다.
여하튼 해결되어서 기쁘다. 오늘 하루 반나절 동안 짜증나서 죽는줄 알았다.

많은 분들에게 도움이 되었으면 한다.
끝.

Ospace.

단순 참고:
Managed Extensions for C++ DLL 프로젝트를 빌드할 때 링커 경고가 발생한다http://support.microsoft.com/kb/814472/ko

Mixed DLL Loading Problem http://msdn.microsoft.com/en-us/library/aa290048(vs.71).aspx

뚱보타잔님의 DLL만들기 http://fattarzan.tistory.com/attachment/dk040000000014.doc(구글로 링크만)

DllEntryPoint, http://winapi.freetechsecrets.com/win32/WIN32DllEntryPoint.htm

반응형