Partilhar via


Execução lado a lado em processo

Nota

Este artigo é específico do .NET Framework. Ele não se aplica a implementações mais recentes do .NET, incluindo o .NET 6 e versões posteriores.

A partir do .NET Framework 4, você pode usar a hospedagem lado a lado em processo para executar várias versões do Common Language Runtime (CLR) em um único processo. Por padrão, os componentes COM gerenciados são executados com a versão do .NET Framework com a qual foram criados, independentemente da versão do .NET Framework carregada para o processo.

Fundo

O .NET Framework sempre forneceu hospedagem lado a lado para aplicativos de código gerenciado, mas antes do .NET Framework 4, ele não fornecia essa funcionalidade para componentes COM gerenciados. No passado, os componentes COM gerenciados que eram carregados em um processo eram executados com a versão do tempo de execução que já estava carregada ou com a versão instalada mais recente do .NET Framework. Se esta versão não fosse compatível com o componente COM, o componente falharia.

O .NET Framework 4 fornece uma nova abordagem para hospedagem lado a lado que garante o seguinte:

  • A instalação de uma nova versão do .NET Framework não tem efeito sobre os aplicativos existentes.

  • Os aplicativos são executados em relação à versão do .NET Framework com a qual foram criados. Eles não usam a nova versão do .NET Framework, a menos que expressamente instruído a fazê-lo. No entanto, é mais fácil para os aplicativos fazer a transição para usar uma nova versão do .NET Framework.

Efeitos sobre usuários e desenvolvedores

  • Usuários finais e administradores de sistema. Esses usuários agora podem ter maior confiança de que, quando instalam uma nova versão do tempo de execução, de forma independente ou com um aplicativo, isso não terá impacto em seus computadores. Os aplicativos existentes continuarão a ser executados como antes.

  • Programadores de aplicações. A hospedagem lado a lado quase não tem efeito sobre os desenvolvedores de aplicativos. Por padrão, os aplicativos sempre são executados em relação à versão do .NET Framework em que foram criados; isso não mudou. No entanto, os desenvolvedores podem substituir esse comportamento e direcionar o aplicativo para ser executado em uma versão mais recente do .NET Framework (consulte o cenário 2).

  • Desenvolvedores e consumidores de bibliotecas. A hospedagem lado a lado não resolve os problemas de compatibilidade que os desenvolvedores de bibliotecas enfrentam. Uma biblioteca que é carregada diretamente por um aplicativo - seja por meio de uma referência direta ou por meio de uma Assembly.Load chamada - continua a usar o tempo de execução do em que é carregada AppDomain . Você deve testar suas bibliotecas em relação a todas as versões do .NET Framework que você deseja suportar. Se um aplicativo for compilado usando o tempo de execução do .NET Framework 4, mas incluir uma biblioteca que foi criada usando um tempo de execução anterior, essa biblioteca também usará o tempo de execução do .NET Framework 4. No entanto, se você tiver um aplicativo que foi criado usando um tempo de execução anterior e uma biblioteca que foi criada usando o .NET Framework 4, você deve forçar seu aplicativo a também usar o .NET Framework 4 (consulte o cenário 3).

  • Desenvolvedores de componentes COM gerenciados. No passado, os componentes COM gerenciados eram executados automaticamente usando a versão mais recente do tempo de execução instalada no computador. Agora você pode executar componentes COM em relação à versão do tempo de execução com a qual eles foram criados.

    Conforme mostrado pela tabela a seguir, os componentes que foram criados com o .NET Framework versão 1.1 podem ser executados lado a lado com os componentes da versão 4, mas não podem ser executados com componentes da versão 2.0, 3.0 ou 3.5, porque a hospedagem lado a lado não está disponível para essas versões.

    Versão do .NET Framework 1.1 2.0 - 3.5 4
    1.1 Não aplicável Não Sim
    2.0 - 3.5 Não Não aplicável Sim
    4 Sim Sim Não aplicável

Nota

As versões 3.0 e 3.5 do .NET Framework são criadas incrementalmente na versão 2.0 e não precisam ser executadas lado a lado. Estas são inerentemente a mesma versão.

Cenários comuns de hospedagem lado a lado

  • Cenário 1: Aplicativo nativo que usa componentes COM criados com versões anteriores do .NET Framework.

    Versões do .NET Framework instaladas: O .NET Framework 4 e todas as outras versões do .NET Framework usadas pelos componentes COM.

    O que fazer: Neste cenário, não faça nada. Os componentes COM serão executados com a versão do .NET Framework com a qual foram registrados.

  • Cenário 2: Aplicativo gerenciado criado com o .NET Framework 2.0 SP1 que você preferiria executar com o .NET Framework 2.0, mas está disposto a ser executado no .NET Framework 4 se a versão 2.0 não estiver presente.

    Versões do .NET Framework instaladas: uma versão anterior do .NET Framework e do .NET Framework 4.

    O que fazer: No arquivo de configuração do aplicativo no diretório do aplicativo, use o< elemento de inicialização> e o <elemento supportedRuntime> da seguinte maneira:

    <configuration>
      <startup >
        <supportedRuntime version="v2.0.50727" />
        <supportedRuntime version="v4.0" />
      </startup>
    </configuration>
    
  • Cenário 3: Aplicativo nativo que usa componentes COM criados com versões anteriores do .NET Framework que você deseja executar com o .NET Framework 4.

    Versões do .NET Framework instaladas: O .NET Framework 4.

    O que fazer: No arquivo de configuração do aplicativo no diretório do aplicativo, use o <startup> elemento com o useLegacyV2RuntimeActivationPolicy atributo definido como true e o <supportedRuntime> elemento definido da seguinte maneira:

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

Exemplo

O exemplo a seguir demonstra um host COM não gerenciado que está executando um componente COM gerenciado usando a versão do .NET Framework que o componente foi compilado para usar.

Para executar o exemplo a seguir, compile e registre o seguinte componente COM gerenciado usando o .NET Framework 3.5. Para registrar o componente, no menu Projeto, clique em Propriedades, clique na guia Construir e marque a caixa de seleção Registrar para interoperabilidade 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);
        }
    }
}

Compile o seguinte aplicativo C++ não gerenciado, que ativa o objeto COM criado pelo exemplo anterior.

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

Consulte também