2009-11-25 13 views
0

J'ai un ancien contrôle COM (Core) qui accepte un IUnknown dans un lavabo. Le but est de permettre au Core de lire/écrire des données via cette interface de récepteur. Les pointeurs Core/Sink sont actuellement utilisés dans les systèmes hérités et ne sont pas facilement modifiables.Implémentation d'un «évier» COM dans le code géré (C#)

Le problème que j'ai est quand je tente d'appeler le noyau à partir du code managé et transmettre un objet qui (tente) pour implémenter le récepteur dans le code managé. J'ai débogué le noyau au point qu'il se prépare à appeler l'évier. Avant (et non après) l'appel, je reçois un message semblable à:

Run-Time Échec de la vérification # 0 - La valeur de l'ESP n'a pas été correctement conservé après un appel de fonction ...

J'ai vu et travaillé à travers ceux-ci dans le code hérité pur, mais l'introduction du code managé m'a rendu perplexe.

Voici les plus petites représentations des deux interfaces que je crois nécessaires.

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 
} 

accès aux données « puits » à partir du IDL (réduit pour la démonstration des problèmes de facilité)

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); 
} 

J'ai essayé une variété d'implémentations de l'évier en C#, sans résultat ou le changement de conditions d'erreur. Voici l'implémentation la plus courante, et oui, j'ai codé à la main la définition de l'interface, en utilisant celle du type lib ne fonctionnait pas. (même problème)

[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

Peut-être intéressant: http://stackoverflow.com/questions/1787422/an-idiomatic-way-of-wrapping-a-possibly-transient-object –

+0

Votre serveur COM natif est-il construit avec MBCS ou Unicode? –

+0

@Ben, merci pour le lien, cependant, cela ne semble pas aider. @Sheng Jiang, le serveur COM est construit avec MBCS. Je peux y apporter des modifications et construire la source; Toutefois, en raison d'autres limitations, il doit rester MBCS et ne peut pas être déplacé vers Unicode. – DevSolo

Répondre

1

Ce problème ESP signifie généralement que vous avez une sorte de mélange entre les bibliothèques d'exécution de vos DLL. Par exemple, dans notre base de code, il y a beaucoup d'objets COM, si l'enregistrement COM actuel de certains de ces objets provient de la version de débogage mais que d'autres sont l'enregistrement des versions, alors vous obtiendrez l'erreur ESP lorsque les méthodes sont appelées les interfaces que ces objets fournissent.

J'ai un script qui enregistre tous les objets COM connus qui se trouvent dans notre base de code.