2013-02-19 1 views
0

최근에 DLL에 COM coclass/인터페이스를 생성하고 구현하는 프로젝트를 상속했습니다. 이 COM DLL은 COM 클래스의 인터페이스에 GUI를 적용하는 응용 프로그램에서 사용됩니다. 이것은 COM DLL을 사용하는 유일한 응용 프로그램입니다. COM을 잘 다루지 못해 좋은 문서를 찾기가 어렵습니다.COM 메소드 및 속성 추가/제거시 고려 사항

내 작업의 일부에는 인터페이스에 더 이상 필요하지 않은 일부 메소드/속성을 추가하는 작업이 포함됩니다. 나는 이것을 달성하기 위해 IDL을 수정해야한다는 것을 배웠다. 지금은 인터페이스의 끝에 새로운 메소드와 속성을 추가하기 만하면 모든 것이 잘 작동하는 것 같습니다. 그러나 속성 중 하나를 제거하면 (예를 들어) 응용 프로그램을 실행하면 문제가 빠르게 발생합니다.

interface IMyComInterface : IDispatch 
    { 
     [id(1), helpstring("method CheckMessage")] HRESULT CheckMessage([in] VARIANT vMsg); 
     [id(2), helpstring("method CheckFolder")] HRESULT CheckFolder([in] VARIANT Folder, [out] VARIANT *pCount, [out, retval] VARIANT *pErrorCount); 
     //[propget, id(3), helpstring("property Flags")] HRESULT Flags([out, retval] VARIANT *pVal); 
     //[propput, id(3), helpstring("property Flags")] HRESULT Flags([in] VARIANT newVal); 
     [propget, id(4), helpstring("property MessageStore")] HRESULT MessageStore([out, retval] VARIANT *pVal); 
     [propput, id(4), helpstring("property MessageStore")] HRESULT MessageStore([in] VARIANT newVal); 
     [propget, id(5), helpstring("property Directory")] HRESULT Directory([out, retval] VARIANT *pVal); 
     [propput, id(5), helpstring("property Directory")] HRESULT Directory([in] VARIANT newVal); 
    } 

나는 그것이 ID 번호 순서가 깨진 것과 관련이 있다고 생각합니다. 나는 모든 것들을 그 아래로 옮길 수 있고 모든 것이 작동 할 것이라고 생각합니다. 그러나 나는이 모든 것을하기위한 적절한 방법에 대해 궁금합니다.

감사합니다.

+0

는 [32 비트 양의 정수 값이 ID가 될 수 있습니다] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa367040(v=vs.85).aspx) 시퀀스에 관계없이. 어떤 라이브러리 (있는 경우)를 사용하여 IDispatch 메서드를 구현 했습니까? Murphy를 방해하지 않으려면 수동으로 .dll, .obj 및 .tlb를 제거하여 shure가되도록 모든 것을 다시 빌드하십시오. – ixe013

+0

(C++로 작성된) GUI 응용 프로그램을 다시 컴파일하면 문제가 해결됩니다. 나는'IDispatch :: Invoke'가 후기 바인딩에서 사용될 때 ID가 중요하다는 것을 알았습니다. 사용하지 않았습니다. –

답변

2

GUI가 IDispatch::Invoke을 사용하여 메소드를 호출하는 경우 메소드 호출이 런타임에 (런타임 바인딩) 해결되기 때문에 인터페이스에서의 변경 사항에 복원력이 있어야합니다 (ID를 동일하게 유지하는 한). VB6 프로그램 및 스크립팅 언어가 이러한 방식으로 작동하는 것이 일반적입니다.

그러나 GUI가 IMyComInterface (C++ 또는 C# 응용 프로그램 일 가능성이 가장 높음)에 대해 직접 컴파일되는 경우 중요한 것은 인터페이스에서 메소드의 정확한 순서입니다. 메서드 호출은 컴파일 타임 (초기 바인딩)에서 확인되고 인터페이스의 메서드 인덱스는 COM 클라이언트에 저장됩니다. IDL에서 메소드를 삭제하면 클라이언트의 모든 함수 호출이 하나씩 해제됩니다. 이것이 결국 새로운 메소드를 추가하는 것이지만, 중간에 메소드를 삭제하지 않는 이유입니다.

(COM DLL과 GUI를 모두 제어하기 때문에) 이러한 모든 문제를 해결하는 가장 간단한 방법은 IDL을 변경 한 후 모든 것을 다시 컴파일해야합니다. 그러나 일반적인 경우에는 모든 인터페이스를 "기능적 메소드 그룹의 변경 불가능한 계약"(source)으로 취급해야하며 COM 인터페이스가 세상에 출시 된 후에는 COM 인터페이스를 수정해서는 안됩니다.

+0

설명해 주셔서 감사합니다. 지금은 의미가 있습니다. COM 클라이언트를 다시 컴파일했고 모든 것이 다시 작동합니다. –

1

COM 클라이언트가 C++ 인 경우 런타임에 바인딩하는 대신 초기 바인딩 (즉, 동일한 인터페이스를 유지하는 레이아웃에 의존한다는 의미)을 사용합니다. 이 경우 DISPID는 후기 바인딩에 사용되며 초기 바인딩에는 사용되지 않기 때문에 DISPID가 무엇인지는 중요하지 않습니다. 따라서 인터페이스에서 메소드/속성을 제거하면 다시 컴파일하지 않으면 클라이언트가 중단됩니다. 이전 상속 새로운 인터페이스를 추가하고 새로운 기능을 추가하는 대신 COM 인터페이스를 변경하지 않는 것이 좋습니다 이유이기도합니다 :

interface IMyComInterface : IDispatch 
{ 
    // existing methods/properties 
} 

interface IMyComInterface2 : IMyComInterface 
{ 
    // new methods/properties 
}