Partager via


Exécution côte à côte in-process

Remarque

Cet article est spécifique à .NET Framework. Elle ne s’applique pas aux implémentations plus récentes de .NET, notamment .NET 6 et versions ultérieures.

À compter de .NET Framework 4, vous pouvez utiliser l’hébergement côte à côte in-process pour exécuter plusieurs versions du CLR (Common Language Runtime) dans un processus unique. Par défaut, les composants COM managés s’exécutent avec la version du .NET Framework qu’ils ont été générés, quelle que soit la version du .NET Framework chargée pour le processus.

Contexte

Le .NET Framework a toujours fourni un hébergement côte à côte pour les applications de code managé, mais avant le .NET Framework 4, il ne fournit pas cette fonctionnalité pour les composants COM managés. Dans le passé, les composants COM gérés qui ont été chargés dans un processus ont été exécutés avec la version du runtime déjà chargée ou avec la dernière version installée du .NET Framework. Si cette version n’était pas compatible avec le composant COM, le composant échouerait.

Le .NET Framework 4 fournit une nouvelle approche de l’hébergement côte à côte qui garantit les éléments suivants :

  • L’installation d’une nouvelle version du .NET Framework n’a aucun effet sur les applications existantes.

  • Les applications s’exécutent sur la version du .NET Framework avec laquelle elles ont été créées. Ils n’utilisent pas la nouvelle version du .NET Framework, sauf indication contraire. Toutefois, il est plus facile pour les applications de passer à l’utilisation d’une nouvelle version du .NET Framework.

Effets sur les utilisateurs et les développeurs

  • Utilisateurs finaux et administrateurs système. Ces utilisateurs peuvent désormais avoir une plus grande confiance que lorsqu’ils installent une nouvelle version du runtime, indépendamment ou avec une application, ils n’auront aucun impact sur leurs ordinateurs. Les applications existantes continueront à s’exécuter comme elles l’ont fait précédemment.

  • Développeurs d’applications. L’hébergement côte à côte n’a presque aucun effet sur les développeurs d’applications. Par défaut, les applications s’exécutent toujours sur la version du .NET Framework sur laquelle elles ont été créées ; cela n’a pas changé. Toutefois, les développeurs peuvent remplacer ce comportement et diriger l’application à s’exécuter sous une version plus récente du .NET Framework (voir le scénario 2).

  • Développeurs de bibliothèques et consommateurs. L’hébergement côte à côte ne résout pas les problèmes de compatibilité auxquels les développeurs de bibliothèques sont confrontés. Une bibliothèque qui est directement chargée par une application ( via une référence directe ou via un Assembly.Load appel) continue d’utiliser le runtime dans lequel AppDomain elle est chargée. Vous devez tester vos bibliothèques sur toutes les versions du .NET Framework que vous souhaitez prendre en charge. Si une application est compilée à l’aide du runtime .NET Framework 4, mais inclut une bibliothèque créée à l’aide d’un runtime antérieur, cette bibliothèque utilise également le runtime .NET Framework 4. Toutefois, si vous avez une application créée à l’aide d’un runtime antérieur et d’une bibliothèque créée à l’aide du .NET Framework 4, vous devez forcer votre application à utiliser également .NET Framework 4 (voir le scénario 3).

  • Développeurs de composants COM managés. Dans le passé, les composants COM gérés s’exécutaient automatiquement à l’aide de la dernière version du runtime installée sur l’ordinateur. Vous pouvez maintenant exécuter des composants COM sur la version du runtime avec laquelle ils ont été générés.

    Comme le montre le tableau suivant, les composants créés avec .NET Framework version 1.1 peuvent s’exécuter côte à côte avec les composants version 4, mais ils ne peuvent pas s’exécuter avec les composants 2.0, 3.0 ou 3.5, car l’hébergement côte à côte n’est pas disponible pour ces versions.

    Version du .NET Framework 1.1 2.0 - 3.5 4
    1.1 Sans objet Non Oui
    2.0 - 3.5 Non Sans objet Oui
    4 Oui Oui Sans objet

Remarque

Les versions 3.0 et 3.5 de .NET Framework sont générées de manière incrémentielle sur la version 2.0 et n’ont pas besoin d’être exécutées côte à côte. Il s’agit en soi de la même version.

Scénarios d’hébergement côte à côte courants

  • Scénario 1 : Application native qui utilise des composants COM créés avec des versions antérieures du .NET Framework.

    Versions de .NET Framework installées : .NET Framework 4 et toutes les autres versions du .NET Framework utilisé par les composants COM.

    Que faire : dans ce scénario, ne faites rien. Les composants COM s’exécutent avec la version du .NET Framework avec laquelle ils ont été inscrits.

  • Scénario 2 : Application managée créée avec .NET Framework 2.0 SP1 que vous préférez exécuter avec .NET Framework 2.0, mais qui est prête à s’exécuter sur .NET Framework 4 si la version 2.0 n’est pas présente.

    Versions de .NET Framework installées : version antérieure du .NET Framework et du .NET Framework 4.

    Que faire : dans le fichier de configuration de l’application dans le répertoire de l’application, utilisez l’élément <de démarrage> et l’élément< SupportedRuntime> défini comme suit :

    <configuration>
      <startup >
        <supportedRuntime version="v2.0.50727" />
        <supportedRuntime version="v4.0" />
      </startup>
    </configuration>
    
  • Scénario 3 : Application native qui utilise des composants COM créés avec des versions antérieures du .NET Framework que vous souhaitez exécuter avec .NET Framework 4.

    Versions de .NET Framework installées : .NET Framework 4.

    Que faire : dans le fichier de configuration de l'application dans le répertoire de l'application, utilisez l'élément <startup> avec l'attribut useLegacyV2RuntimeActivationPolicy défini sur true et l'élément <supportedRuntime> défini comme suit :

    <configuration>
      <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0" />
      </startup>
    </configuration>
    

Exemple :

L’exemple suivant illustre un hôte COM non managé qui exécute un composant COM managé à l’aide de la version du .NET Framework que le composant a été compilé à utiliser.

Pour exécuter l’exemple suivant, compilez et inscrivez le composant COM managé suivant à l’aide de .NET Framework 3.5. Pour inscrire le composant, dans le menu Projet , cliquez sur Propriétés, cliquez sur l’onglet Générer , puis activez la case à cocher Inscrire pour l’interopérabilité COM .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace BasicComObject
{
    [ComVisible(true), Guid("9C99C4B5-CA54-4c58-8988-49B6811BA53B")]
    public class MyObject : SimpleObjectModel.IPrintInfo
    {
        public MyObject()
        {
        }
        public void PrintInfo()
        {
            Console.WriteLine("MyObject was activated in {0} runtime in:\n\tAppDomain {1}:{2}", System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion(), AppDomain.CurrentDomain.Id, AppDomain.CurrentDomain.FriendlyName);
        }
    }
}

Compilez l’application C++ non managée suivante, qui active l’objet COM créé par l’exemple précédent.

#include "stdafx.h"
#include <string>
#include <iostream>
#include <objbase.h>
#include <string.h>
#include <process.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    char input;
    CoInitialize(NULL) ;
    CLSID clsid;
    HRESULT hr;
    HRESULT clsidhr = CLSIDFromString(L"{9C99C4B5-CA54-4c58-8988-49B6811BA53B}",&clsid);
    hr = -1;
    if (FAILED(clsidhr))
    {
        printf("Failed to construct CLSID from String\n");
    }
    UUID id = __uuidof(IUnknown);
    IUnknown * pUnk = NULL;
    hr = ::CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,id,(void **) &pUnk);
    if (FAILED(hr))
    {
        printf("Failed CoCreateInstance\n");
    }else
    {
        pUnk->AddRef();
        printf("Succeeded\n");
    }

    DISPID dispid;
    IDispatch* pPrintInfo;
    pUnk->QueryInterface(IID_IDispatch, (void**)&pPrintInfo);
    OLECHAR FAR* szMethod[1];
    szMethod[0]=OLESTR("PrintInfo");
    hr = pPrintInfo->GetIDsOfNames(IID_NULL,szMethod, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
    DISPPARAMS dispparams;
    dispparams.cNamedArgs = 0;
    dispparams.cArgs = 0;
    VARIANTARG* pvarg = NULL;
    EXCEPINFO * pexcepinfo = NULL;
    WORD wFlags = DISPATCH_METHOD ;
;
    LPVARIANT pvRet = NULL;
    UINT * pnArgErr = NULL;
    hr = pPrintInfo->Invoke(dispid,IID_NULL, LOCALE_USER_DEFAULT, wFlags,
        &dispparams, pvRet, pexcepinfo, pnArgErr);
    printf("Press Enter to exit");
    scanf_s("%c",&input);
    CoUninitialize();
    return 0;
}

Voir aussi