Utilisation des assemblys d’interopérabilité de Visual Studio

Les assemblys d’interopérabilité Visual Studio permettent aux applications managées d’accéder aux interfaces COM qui fournissent une extensibilité Visual Studio. Il existe des différences entre les interfaces COM droites et leurs versions d’interopérabilité. Par exemple, les HRESULT sont généralement représentés en tant que valeurs int et doivent être gérés de la même façon que les exceptions, et les paramètres (en particulier les paramètres out) sont traités différemment.

Gestion des HRESULT retournés au code managé à partir de COM

Quand vous appelez une interface COM à partir de code managé, examinez la valeur HRESULT et levez une exception si nécessaire. La classe ErrorHandler contient la méthode ThrowOnFailure qui lève une exception COM, selon la valeur HRESULT qui lui est passée.

Par défaut, ThrowOnFailure lève une exception dès lors qu’elle est passée à un HRESULT qui a une valeur inférieure à zéro. Dans les cas où ces valeurs HRESULT sont des valeurs acceptables et quand aucune exception ne doit être levée, les valeurs des HRESULT supplémentaires doivent être passées à ThrowOnFailure une fois les valeurs testées. Si la valeur HRESULT testée correspond à une valeur HRESULT explicitement passée à ThrowOnFailure, aucune exception n’est levée.

Remarque

La VSConstants classe contient des constantes pour HRESULTS courants, par exemple S_OK , et , et E_NOTIMPLVisual Studio HRESULTS, par exemple, VS_E_INCOMPATIBLEDOCDATA et VS_E_UNSUPPORTEDFORMAT. VSConstants fournit également les méthodes Succeeded et Failed qui correspondent aux macros SUCCEEDED et FAILED dans COM.

Par exemple, considérez l’appel de fonction suivant, dans lequel E_NOTIMPL est une valeur de retour acceptable, alors que les autres valeurs HRESULT inférieures à zéro représentent une erreur.

int hr = MyInterface.MyFunction(cmdID);
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOTIMPL);

S’il existe plusieurs valeurs de retour acceptables, les autres valeurs HRESULT peuvent être simplement ajoutées à la liste dans l’appel à ThrowOnFailure.

int hr = MyInterface.MyFunction(cmdID);
ErrorHandler.ThrowOnFailure(hr, VSConstants.E_NOINTERFACE, VSConstants.E_NOTIMPL);

Retour de valeurs HRESULT à COM à partir de code managé

Si aucune exception ne se produit, le code managé retourne S_OK à la fonction COM qui l’a appelé. COM interop prend en charge les exceptions courantes qui sont fortement typées dans du code managé. Par exemple, une méthode qui reçoit un argument null inacceptable lève une ArgumentNullException.

Si vous ne savez pas quelle exception lever, alors que vous connaissez la valeur HRESULT à retourner à COM, vous pouvez utiliser la méthode ThrowExceptionForHR pour lever une exception appropriée. Cela fonctionne même avec une erreur non standard, par exemple, VS_E_INCOMPATIBLEDOCDATA. ThrowExceptionForHR essaie de mapper la valeur HRESULT qui lui est passée sur une exception fortement typée. Si ce n’est pas possible, une exception COM générique est levée. Le résultat final est que la valeur HRESULT que vous passez à ThrowExceptionForHR à partir du code managé est retournée à la fonction COM qui l’a appelée.

Remarque

Les exceptions nuisent aux performances et ont vocation à indiquer des conditions anormales pour le programme. Les conditions qui se produisent souvent doivent être gérées instantanément, au lieu de lever une exception.

Paramètres IUnknown passés en tant que Type void**

Recherchez les paramètres [out] définis comme type void ** dans l’interface COM, mais qui sont définis comme [``iid_is``] dans le prototype de méthode d’assembly d’interopérabilité Visual Studio.

Parfois, une interface COM génère un IUnknown objet et l’interface COM le transmet en tant que type void **. Ces interfaces sont particulièrement importantes, car si la variable est définie comme [out] dans l’IDL, l’objet IUnknown est comptabilisé par référence avec la AddRef méthode. Une fuite de mémoire se produit si l’objet n’est pas géré correctement.

Remarque

Un IUnknown objet créé par l’interface COM et retourné dans une variable [out] provoque une fuite de mémoire si elle n’est pas explicitement libérée.

Les méthodes managées qui gèrent ces objets doivent traiter IntPtr comme un pointeur vers un IUnknown objet et appeler la GetObjectForIUnknown méthode pour obtenir l’objet. L’appelant doit ensuite convertir la valeur de retour en n’importe quel type approprié. Lorsque l’objet n’est plus nécessaire, appelez-le Release pour le libérer.

Voici un exemple d’appel de la méthode et de gestion de l’objet QueryViewInterfaceIUnknown correctement :

MyClass myclass;
Object object;
IntPtr pObj;
Guid iid = Typeof(MyClass).Guid;
int hr = windowFrame.QueryViewInterface(ref iid, out pObj);
if (NativeMethods.Succeeded(hr))
{
    try
    {
        object = Marshal.GetObjectForIUnknown(pObj);
        myclass = object;
    }
    finally
    {
        Marshal.Release(pObj);
    }
}
else
{
    // error calling QueryViewInterface
}

Remarque

Les méthodes suivantes sont connues pour passer des IUnknown pointeurs d’objet en tant que type IntPtr. Gérez-les comme décrit dans cette section.

Paramètres facultatifs [out]

Recherchez les paramètres définis comme un type de données [out] (intet objectainsi de suite) dans l’interface COM, mais qui sont définis en tant que tableaux du même type de données dans le prototype de méthode d’assembly Visual Studio Interop.

Certaines interfaces COM, telles que GetCfgs, traitent les paramètres [out] comme facultatifs. Si un objet n’est pas obligatoire, ces interfaces COM retournent un null pointeur comme valeur de ce paramètre au lieu de créer l’objet [out]. C'est la procédure normale. Pour ces interfaces, null les pointeurs sont supposés dans le cadre du comportement correct de VSPackage et aucune erreur n’est retournée.

Étant donné que le CLR n’autorise pas la valeur d’un paramètre [out] à être null, une partie du comportement conçu de ces interfaces n’est pas directement disponible dans le code managé. Les méthodes d’assembly d’interopérabilité Visual Studio pour les interfaces affectées fonctionnent autour du problème en définissant les paramètres pertinents en tant que tableaux, car le CLR autorise le passage de null tableaux.

Les implémentations gérées de ces méthodes doivent placer un null tableau dans le paramètre lorsqu’il n’y a rien à retourner. Sinon, créez un tableau d’un élément du type correct et placez la valeur de retour dans le tableau.

Les méthodes managées qui reçoivent des informations d’interfaces avec des paramètres facultatifs [out] reçoivent le paramètre en tant que tableau. Examinez simplement la valeur du premier élément du tableau. Si ce n’est pas nullle cas, traitez le premier élément comme s’il s’agissait du paramètre d’origine.

Passage de constantes dans les paramètres de pointeur

Recherchez les paramètres définis en tant que pointeurs [in] dans l’interface COM, mais qui sont définis comme un IntPtr type dans le prototype de méthode d’assembly Visual Studio Interop.

Un problème similaire se produit lorsqu’une interface COM transmet une valeur spéciale, telle que 0, -1 ou -2, au lieu d’un pointeur d’objet. Contrairement à Visual C++, le CLR n’autorise pas la conversion des constantes en tant qu’objets. Au lieu de cela, l’assembly d’interopérabilité Visual Studio définit le paramètre en tant que IntPtr type.

Les implémentations managées de ces méthodes doivent tirer parti du fait que la IntPtr classe possède à la fois int et void * des constructeurs pour créer un IntPtr objet ou une constante entière, selon les besoins.

Les méthodes gérées qui reçoivent IntPtr des paramètres de ce type doivent utiliser les opérateurs de conversion de IntPtr type pour gérer les résultats. Tout d’abord, convertissez-le IntPtrint et testez-le par rapport aux constantes entières pertinentes. Si aucune valeur ne correspond, convertissez-la en objet du type requis et continuez.

Pour obtenir des exemples de ceci, consultez OpenStandardEditor et OpenSpecificEditor.

Valeurs de retour OLE passées en tant que paramètres [out]

Recherchez les méthodes qui ont une retval valeur de retour dans l’interface COM, mais qui ont une int valeur de retour et un paramètre de tableau [out] supplémentaire dans le prototype de méthode d’assembly Visual Studio Interop. Il doit être clair que ces méthodes nécessitent une gestion spéciale, car les prototypes de méthode d’assembly d’interopérabilité Visual Studio ont un paramètre plus que les méthodes d’interface COM.

De nombreuses interfaces COM qui traitent de l’activité OLE envoient des informations sur l’état OLE au programme appelant stocké dans la retval valeur de retour de l’interface. Au lieu d’utiliser une valeur de retour, les méthodes d’assembly Visual Studio interopérabilité correspondantes renvoient les informations au programme appelant stocké dans un paramètre de tableau [out].

Les implémentations gérées de ces méthodes doivent créer un tableau à élément unique du même type que le paramètre [out] et le placer dans le paramètre. La valeur de l’élément de tableau doit être identique à la valeur COM retvalappropriée.

Les méthodes managées qui appellent des interfaces de ce type doivent extraire le premier élément du tableau [out]. Cet élément peut être traité comme s’il s’agissait d’une retval valeur de retour de l’interface COM correspondante.