2009-11-25 2 views
0

У меня есть устаревший COM-контроль (Core), который принимает IUnknown к раковине. Цель состоит в том, чтобы позволить Core считывать/записывать данные через этот интерфейс приемника. Указатели Core/Sink в настоящее время используются в устаревших системах и не легко модифицируются.Внедрение COM-раковины в управляемом (C#) коде

Проблема, с которой я сталкиваюсь, заключается в попытке вызвать ядро ​​из управляемого кода и передать объект, который (пытается) реализовать приемник в управляемом коде. Я отлаживал Core до такой степени, что он готовится к вызову раковины. До (не после) вызова, я получаю сообщение, похожее на:

Run-Time Check Failure # 0 - значение ESP не была должным образом сохраненные через вызов функции ...

Я видел и работал с ними в чистом устаревшем коде, но введение управляемого кода вызывает у меня недоумение.

Здесь представлены наименьшие изображения двух интерфейсов, которые, я считаю, необходимы.

interface ICore : IDispatch 
{ 
    [id(1), helpstring("method Init")] HRESULT Init([in] IUnknown *pDataManSink); 

    HRESULT FireOnImport([in] LPCOLESTR pszFormName, [in] LPCOLESTR pszTagName, [in] VARIANT pszData); 

    ... more methods 
} 

данные доступ «раковина», как из IDL (пониженная для проблемной легкости демонстрации)

interface IDataManagerSinkEx : IUnknown 
{ 
    [helpstring("method ReadData")] HRESULT ReadData([in] LPCTSTR pszDataKey, [out, retval] BSTR* pbsData); 
    [helpstring("method WriteData")] HRESULT WriteData([in] LPCTSTR pszDataKey, [in] LPCTSTR pszData); 
    [helpstring("method ReadDataEx")] HRESULT ReadTagEx([in] LPCTSTR pszDataKey, [out] short *pwExtraInfoOut, [out, retval] BSTR *pbsData); 
    [helpstring("method WriteDataEx")] HRESULT WriteTagEx([in] LPCTSTR pszDataKey, [in] short wExtraInfo, [in] LPCTSTR pszData); 
} 

Я пробовал различные реализации раковины в C#, но безрезультатно или изменить в условия ошибки. Вот самая последняя реализация, и да, я вручную кодировал определение интерфейса, так как использование одного из типа lib не сработало. (Тот же вопрос)

[ComImport] 
[Guid("AB79770E-8143-45E6-B082-E985E6DFA5CB")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IMyDataManagerSinkEx 
{ 
    [PreserveSig] 
    int ReadData([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out string data); 

    [PreserveSig] 
    int WriteTag([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, [MarshalAs(UnmanagedType.LPStr)]string pszData); 

    [PreserveSig] 
    int ReadTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out short pwExraInfoOut, out string dataOut); 

    [PreserveSig] 
    int WriteTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, short wExtraInfo, [MarshalAs(UnmanagedType.LPStr)]string pszData); 
} 

class public SinkImpl : IMyDataManagerSinkEx 
{ 
    [PreserveSig] 
    public int ReadData([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out string data) 
    { 
    throw new NotImplementedException(); 
    } 

    [PreserveSig] 
    public int WriteTag([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, [MarshalAs(UnmanagedType.LPStr)]string pszData) 
    { 
    throw new NotImplementedException(); 
    } 

    [PreserveSig] 
    public int ReadTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, out short pwExraInfoOut, out string dataOut) 
    { 
    throw new NotImplementedException(); 
    } 

    [PreserveSig] 
    public int WriteTagEx([MarshalAs(UnmanagedType.LPStr)]string pszDataKey, short wExtraInfo, [MarshalAs(UnmanagedType.LPStr)]string pszData) 
    { 
    throw new NotImplementedException(); 
    } 
} 
+0

Возможно интерес: http://stackoverflow.com/questions/1787422/an-idiomatic-way-of-wrapping-a-possible-transient-object –

+0

Является ли ваш собственный COM-сервер построенным с помощью MBCS или Unicode? –

+0

@Ben, спасибо за ссылку, однако, похоже, это не помогает. @ Шэн Цзян, сервер COM построен с MBCS. Я могу внести в него изменения и построить источник; однако из-за других ограничений он должен оставаться MBCS и не может быть перемещен в Юникод. – DevSolo

ответ

1

Эта проблема ESP обычно означает, что у вас есть какая-то смесь между библиотеками времени выполнения ваших библиотек DLL. Например, в нашей базе кода есть много COM-объектов, если текущая запись COM некоторых из этих объектов из сборки отладки, а другие - из версий выпуска, тогда вы получите ошибку ESP при вызове методов интерфейсы, которые предоставляют эти объекты.

У меня есть сценарий, который регистрирует все известные COM-объекты, которые находятся в нашей кодовой базе.

Смежные вопросы