2009-10-23 2 views
3

Мы пытаемся заменить COM-сервер, написанный для приложения VB6C# - написание COM-сервер - Свойства, отображенные методы

Мы не имеем доступа к исходному коду.

По какой-то причине, приложение VB6 может позвонить в наш конструктор, но затем он получает:

System Error & H80004002. Нет такого интерфейса .

Я предполагаю, что когда он пытается получить интерфейс с QueryInterface.

У нас есть сборка, правильно отправленная через regasm/tlb и gacutil, но затем я заметил что-то странное. Я открыл результирующий файл .tlb, созданный для нашей сборки, и заметил, что все свойства моего интерфейса отображаются как методы.

Является ли это чем-то инструментом .Net? И будет ли это причиной моей проблемы?

Вот полное определение TLB для исходного файла:

// Generated .IDL file (by the OLE/COM Object Viewer) 
// 
// typelib filename: UtopiaKeyboard.tlb 

[ 
    uuid(9B4E1840-FF65-11CF-AA2E-0020AFA49D5A), 
    version(1.0), 
    helpstring("OPOS POSKeyboard OLE Control") 
] 
library POSKEYBOARDLib 
{ 
    // TLib :  // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} 
    importlib("STDOLE2.TLB"); 

    // Forward declare all types defined in this typelib 
    dispinterface _DPOSKeyboard; 
    dispinterface _DPOSKeyboardEvents; 

    [ 
     uuid(9B4E1841-FF65-11CF-AA2E-0020AFA49D5A), 
     helpstring("Dispatch interface for OPOS POSKeyboard OLE Control"), 
     hidden 
    ] 
    dispinterface _DPOSKeyboard { 
     properties: 
      [id(0x00000001)    
] 
      BSTR CheckHealthText; 
      [id(0x00000002)    
] 
      VARIANT_BOOL Claimed; 
      [id(0x00000003)    
] 
      VARIANT_BOOL DataEventEnabled; 
      [id(0x00000004)    
] 
      VARIANT_BOOL DeviceEnabled; 
      [id(0x00000005)    
] 
      VARIANT_BOOL FreezeEvents; 
      [id(0x00000006)    
] 
      long ResultCode; 
      [id(0x00000007)    
] 
      long ResultCodeExtended; 
      [id(0x00000008)    
] 
      long State; 
      [id(0x00000009)    
] 
      BSTR ControlObjectDescription; 
      [id(0x0000000a)    
] 
      long ControlObjectVersion; 
      [id(0x0000000b)    
] 
      BSTR ServiceObjectDescription; 
      [id(0x0000000c)    
] 
      long ServiceObjectVersion; 
      [id(0x0000000d)    
] 
      BSTR DeviceDescription; 
      [id(0x0000000e)    
] 
      BSTR DeviceName; 
      [id(0x0000000f)    
] 
      long POSKeyData; 
      [id(0x0000001a)    
] 
      VARIANT_BOOL AutoDisable; 
      [id(0x0000001b)    
] 
      long BinaryConversion; 
      [id(0x0000001c)    
] 
      long DataCount; 
      [id(0x0000001d)    
] 
      VARIANT_BOOL CapKeyUp; 
      [id(0x0000001e)    
] 
      long EventTypes; 
      [id(0x0000001f)    
] 
      long POSKeyEventType; 
      [id(0x00000021)    
] 
      long CapPowerReporting; 
      [id(0x00000022)    
] 
      long PowerNotify; 
      [id(0x00000023)    
] 
      long PowerState; 
     methods: 
      [id(0x00000010)] 
      long Open([in] BSTR DeviceName); 
      [id(0x00000011)] 
      long Close(); 
      [id(0x00000012)] 
      long Claim([in] long Timeout); 
      [id(0x00000013)] 
      long Release(); 
      [id(0x00000014)] 
      long CheckHealth([in] long Level); 
      [id(0x00000015)] 
      long ClearInput(); 
      [id(0x00000016)] 
      long DirectIO(
          [in] long Command, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000017)] 
      void SOData([in] long Status); 
      [id(0x00000018)] 
      void SODirectIO(
          [in] long EventNumber, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000019)] 
      void SOError(
          [in] long ResultCode, 
          [in] long ResultCodeExtended, 
          [in] long ErrorLocus, 
          [in, out] long* pErrorResponse); 
      [id(0x00000020)] 
      long SOProcessID(); 
      [id(0x00000024)] 
      void SOStatusUpdate([in] long Status); 
    }; 

    [ 
     uuid(9B4E1842-FF65-11CF-AA2E-0020AFA49D5A), 
     helpstring("Event interface for OPOS POSKeyboard OLE Control") 
    ] 
    dispinterface _DPOSKeyboardEvents { 
     properties: 
     methods: 
      [id(0x00000001)] 
      void DataEvent([in] long Status); 
      [id(0x00000002)] 
      void DirectIOEvent(
          [in] long EventNumber, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000003)] 
      void ErrorEvent(
          [in] long ResultCode, 
          [in] long ResultCodeExtended, 
          [in] long ErrorLocus, 
          [in, out] long* pErrorResponse); 
      [id(0x00000004)] 
      void StatusUpdateEvent([in] long Status); 
    }; 

    [ 
     uuid(9B4E1843-FF65-11CF-AA2E-0020AFA49D5A), 
     helpstring("OPOS POSKeyboard OLE Control"), 
     control 
    ] 
    coclass POSKeyboard { 
     [default] dispinterface _DPOSKeyboard; 
     [default, source] dispinterface _DPOSKeyboardEvents; 
    }; 
}; 

Вот генерировать TLB для моей сборки .Net:

// Generated .IDL file (by the OLE/COM Object Viewer) 
// 
// typelib filename: POSKEYBOARDLib.tlb 

[ 
    uuid(9B4E1840-FF65-11CF-AA2E-0020AFA49D5A), 
    version(1.0), 
    custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "POSKEYBOARDLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5824208931aaf68b") 

] 
library POSKEYBOARDLib 
{ 
    // TLib :  // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D} 
    importlib("mscorlib.tlb"); 
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} 
    importlib("STDOLE2.TLB"); 

    // Forward declare all types defined in this typelib 
    dispinterface _DPOSKeyboard; 
    dispinterface _DPOSKeyboardEvents; 

    [ 
     uuid(9B4E1841-FF65-11CF-AA2E-0020AFA49D5A), 
     version(1.0), 
     custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib._DPOSKeyboard")  

    ] 
    dispinterface _DPOSKeyboard { 
     properties: 
     methods: 
      [id(0x00000001), propget] 
      BSTR CheckHealthText(); 
      [id(0x00000001), propput] 
      void CheckHealthText([in] BSTR rhs); 
      [id(0x00000002), propget] 
      VARIANT_BOOL Claimed(); 
      [id(0x00000002), propput] 
      void Claimed([in] VARIANT_BOOL rhs); 
      [id(0x00000003), propget] 
      VARIANT_BOOL DataEventEnabled(); 
      [id(0x00000003), propput] 
      void DataEventEnabled([in] VARIANT_BOOL rhs); 
      [id(0x00000004), propget] 
      VARIANT_BOOL DeviceEnabled(); 
      [id(0x00000004), propput] 
      void DeviceEnabled([in] VARIANT_BOOL rhs); 
      [id(0x00000005), propget] 
      VARIANT_BOOL FreezeEvents(); 
      [id(0x00000005), propput] 
      void FreezeEvents([in] VARIANT_BOOL rhs); 
      [id(0x00000006), propget] 
      long ResultCode(); 
      [id(0x00000006), propput] 
      void ResultCode([in] long rhs); 
      [id(0x00000007), propget] 
      long ResultCodeExtended(); 
      [id(0x00000007), propput] 
      void ResultCodeExtended([in] long rhs); 
      [id(0x00000008), propget] 
      long State(); 
      [id(0x00000008), propput] 
      void State([in] long rhs); 
      [id(0x00000009), propget] 
      BSTR ControlObjectDescription(); 
      [id(0x00000009), propput] 
      void ControlObjectDescription([in] BSTR rhs); 
      [id(0x0000000a), propget] 
      long ControlObjectVersion(); 
      [id(0x0000000a), propput] 
      void ControlObjectVersion([in] long rhs); 
      [id(0x0000000b), propget] 
      BSTR ServiceObjectDescription(); 
      [id(0x0000000b), propput] 
      void ServiceObjectDescription([in] BSTR rhs); 
      [id(0x0000000c), propget] 
      long ServiceObjectVersion(); 
      [id(0x0000000c), propput] 
      void ServiceObjectVersion([in] long rhs); 
      [id(0x0000000d), propget] 
      BSTR DeviceDescription(); 
      [id(0x0000000d), propput] 
      void DeviceDescription([in] BSTR rhs); 
      [id(0x0000000e), propget] 
      BSTR DeviceName(); 
      [id(0x0000000e), propput] 
      void DeviceName([in] BSTR rhs); 
      [id(0x0000000f), propget] 
      long POSKeyData(); 
      [id(0x0000000f), propput] 
      void POSKeyData([in] long rhs); 
      [id(0x00000010)] 
      long Open([in] BSTR DeviceName); 
      [id(0x00000011)] 
      long Close(); 
      [id(0x00000012)] 
      long Claim([in] long Timeout); 
      [id(0x00000013)] 
      long Release(); 
      [id(0x00000014)] 
      long CheckHealth([in] long Level); 
      [id(0x00000015)] 
      long ClearInput(); 
      [id(0x00000016)] 
      long DirectIO(
          [in] long Command, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000017)] 
      void SOData([in] long Status); 
      [id(0x00000018)] 
      void SODirectIO(
          [in] long EventNumber, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000019)] 
      void SOError(
          [in] long ResultCode, 
          [in] long ResultCodeExtended, 
          [in] long ErrorLocus, 
          [in, out] long* pErrorResponse); 
      [id(0x0000001a), propget] 
      VARIANT_BOOL AutoDisable(); 
      [id(0x0000001a), propput] 
      void AutoDisable([in] VARIANT_BOOL rhs); 
      [id(0x0000001b), propget] 
      long BinaryConversion(); 
      [id(0x0000001b), propput] 
      void BinaryConversion([in] long rhs); 
      [id(0x0000001c), propget] 
      long DataCount(); 
      [id(0x0000001c), propput] 
      void DataCount([in] long rhs); 
      [id(0x0000001d), propget] 
      VARIANT_BOOL CapKeyUp(); 
      [id(0x0000001d), propput] 
      void CapKeyUp([in] VARIANT_BOOL rhs); 
      [id(0x0000001e), propget] 
      long EventTypes(); 
      [id(0x0000001e), propput] 
      void EventTypes([in] long rhs); 
      [id(0x0000001f), propget] 
      long POSKeyEventType(); 
      [id(0x0000001f), propput] 
      void POSKeyEventType([in] long rhs); 
      [id(0x00000020)] 
      long SOProcessID(); 
      [id(0x00000021), propget] 
      long CapPowerReporting(); 
      [id(0x00000021), propput] 
      void CapPowerReporting([in] long rhs); 
      [id(0x00000022), propget] 
      long PowerNotify(); 
      [id(0x00000022), propput] 
      void PowerNotify([in] long rhs); 
      [id(0x00000023), propget] 
      long PowerState(); 
      [id(0x00000023), propput] 
      void PowerState([in] long rhs); 
      [id(0x00000024)] 
      void SOStatusUpdate([in] long Status); 
    }; 

    [ 
     uuid(9B4E1842-FF65-11CF-AA2E-0020AFA49D5A), 
     version(1.0), 
     custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib._DPOSKeyboardEvents")  

    ] 
    dispinterface _DPOSKeyboardEvents { 
     properties: 
     methods: 
      [id(0x00000001)] 
      void DataEvent([in] long Status); 
      [id(0x00000002)] 
      void DirectIOEvent(
          [in] long EventNumber, 
          [in, out] long* pData, 
          [in, out] BSTR* pString); 
      [id(0x00000003)] 
      void ErrorEvent(
          [in] long ResultCode, 
          [in] long ResultCodeExtended, 
          [in] long ErrorLocus, 
          [in, out] long* pErrorResponse); 
      [id(0x00000004)] 
      void StatusUpdateEvent([in] long Status); 
    }; 

    [ 
     uuid(9B4E1843-FF65-11CF-AA2E-0020AFA49D5A), 
     version(1.0), 
     custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib.POSKeyboard") 
    ] 
    coclass POSKeyboard { 
     interface _Object; 
     [default] dispinterface _DPOSKeyboard; 
     [default, source] dispinterface _DPOSKeyboardEvents; 
    }; 
}; 

Как-то мои свойства перечислены как методы ... Даже если я добавлю PreserveSig, он все еще записывает 2 метода вместо их свойств.

Какие изменения должны я попытаться сделать его идентичным исходному tlb? Или, по крайней мере, заставить его работать.

UPDATE: Найдено, где у меня не было DispIdAttribute в моем интерфейсе событий. Исправлено это, но приложение VB6 по-прежнему терпит неудачу с той же ошибкой.

ответ

0

Ну, я понял это ...

Я декомпилированы с vb6 декомпилятором на целевом приложении и экспортируется как проект VB6.

Открыт с VS 2008, обновлен до версии VB .Net.

Отказалось от приложения и увидела ошибку «невозможно передать в IOleObject».

Был ли поиск в Google обнаружен, что System.Windows.Forms.Control реализует этот интерфейс, поэтому наследование с Control исправило мою проблему.

2

У вас нет COM-интерфейса с именами, которые перекрывают имена методов IUnknown (QueryInterface, AddRef и Release).

Update

Чтобы ваш C# класс генерировать dispinteface, украсить свой класс с ClassInterfaceAttribute (т.е. IDisptach интерфейс для связывания автоматизации OLE.):

[ClassInterface(ClassInterfaceType.AutoDispatch)] 
class myClass 
{ 
    public string Foo {get;} 
    public long Bar(); 
} 

Это создаст свойство автоматизации Foo и метод Bar, в отличие от необработанного COM-интерфейса.

+0

Как-то оригинальное приложение делает это ... Если я открою свой файл ocx с помощью OleView.exe, у него явно есть метод с именем Release(). Я отправлю исходный файл tlb для вас. – jonathanpeppers

+0

Это дисперсия, поэтому «Release» вызывается с IDispatch :: Invoke (0x00000013, ...). Я не думаю, что есть также IDPOSKeyboard, который расширяет IDispatch и имеет свою собственную «Release», COM-интерфейсы - это vtables, и afaik vtable не может поддерживать это поведение. Прошло некоторое время с тех пор, как я выполнил любую работу OLE/COM, поэтому я мог кое-что забыть ... –

+0

Возможно, вы должны украсить класс C# '[ClassInterface (AutoDual)]' или '[ClassInterface (AutoDispatch))] ', поэтому он также создает интерфейс IDispatch, а не простой COM-интерфейс. –

1

Вы когда-нибудь пробовали использовать информацию, содержащуюся в ссылке:
Visual Basic: Inspect COM Components Using the TypeLib Information Object Library

[EDIT]
Смотрите, если tlbimp.exe инструмент может помочь вам.

+0

Я использовал tlbimp и браузер объектов в VS 2008, в первую очередь, чтобы сгенерировать мои классы в качестве отправной точки. – jonathanpeppers