Este artigo foi traduzido por máquina.

Tudo sobre CLR

In-Process Side-by-Side

Jesse Kaplan

Poste perguntas e comentários no do Blog da equipe de CLR.

Como criamos o .NET Framework 4, um dos mais difíceis problemas enfrentados por nós foi manter a compatibilidade com versões anteriores ao ainda adicionar novos recursos e funcionalidade. Podemos seguido estritos processos que exigem aprovação para quaisquer alterações podem introduzir problemas de compatibilidade — foram rejeitada maioria — e executou um laboratório de compatibilidade com centenas de aplicativos reais para localizar qualquer quebras não intencionais.

Mas sempre podemos corrigir um bug é o risco que alguns aplicativos dependentes desse comportamento errado. Às vezes aplicativos assumir dependências que podemos avisado contra, como o comportamento das APIs particulares ou o texto de descrição de exceções.

Desde o .NET Framework foi introduzido, que tivemos uma boa solução para compatibilidade de aplicativo: permitir que várias versões do .NET Framework para ser instalado na mesma máquina ao mesmo tempo. Isso permite que dois aplicativos diferentes, criado contra duas versões diferentes e instalado em uma máquina, para cada execução contra a versão apropriada.

Problemas de suplemento

Isso funciona bem quando cada aplicativo obtém seu próprio processo, mas os suplementos são problemas muito mais difícil. Imagine que estiver executando um programa, como o Outlook hospeda suplementos COM, incluindo gerenciados suplementos COM e você tem duas versões do runtime — e os suplementos criados contra cada um — instalado na sua máquina. Qual runtime deve escolher? Carregar um suplemento mais recente em um runtime antigo claramente não vai funcionar.

Por outro lado, causa de alto nível de compatibilidade, um suplemento antigo geralmente executará fino em um tempo de execução mais recente. Para dar a todos os suplementos melhor chance de trabalhar, podemos escolher sempre o tempo de execução mais recente para ativação de COM gerenciados. Mesmo se você tiver somente antigos suplementos instalados, não há nenhuma maneira para que possamos saber que quando esse suplemento obtém ativado, então o tempo de execução mais recente ainda obtém carregado.

Um efeito colateral infeliz dessa diretiva ativação é que, quando um usuário instala um novo aplicativo com uma nova versão do runtime, aplicativos completamente não relacionados que usam gerenciado suplementos COM, repentinamente criado contra versões mais antigas, iniciar executando em um tempo de execução mais recente e pode falhar.

Para o .NET Framework 3.0 e 3.5, podemos resolveu esse problema através de uma diretiva extremamente estrito: cada lançamento foi aditivas e somente adicionado novo 
assemblies para a versão anterior com o mesmo runtime abaixo. Isso impediu quaisquer problemas de compatibilidade ao instalar em uma máquina executando o .NET Framework 2.0. Isso significa que quando você estiver executando um aplicativo no .NET Framework 3.5, você está realmente executando em runtime 2.0, com alguns assemblies extras na parte superior do. No entanto, isso também significa que podemos não pôde inovar nos assemblies do .NET 2.0, incluem funcionalidades chaves, como o coletor de lixo, just in time (JIT) e bibliotecas de classe base.

Com o .NET Framework 4 implementamos uma abordagem que permite compatibilidade alta, incluindo nunca quebrando suplementos existentes, 
and também nos permite inovar na principal. Agora podemos pode executar suplementos .NET 2.0 e .NET 4 no mesmo processo, ao mesmo tempo. Chamamos essa abordagem-Process--lado ou -PROC. SxS.

Enquanto-PROC. SxS resolve os problemas de compatibilidade mais comuns, não corrigir tudo. Nesta coluna, que descreveremos mais sobre por que decidimos criar-PROC. SxS, como funciona e quais problemas não resolve. Para escrever aplicativos normais ou suplementos de pessoas, SxS PROC. principalmente simplesmente funciona — as coisas direita todos acontecem automaticamente. Para aqueles que estão escrevendo hosts podem aproveitar-PROC. SxS, nós também vai descrever as APIs de hospedagem atualizadas e fornecer algumas diretrizes para usá-los.

Viagem para Office de Ray Ozzie

Quase todos os executivos alto nível do Microsoft foram repentinamente não é possível verificar o email em qualquer de suas máquinas principais atrasado no 2005. Sem motivo aparente, sempre que eles aberto Outlook poderão travar, reiniciar e falha novamente em um loop contínuo. Não havia nenhum atualizações recentes para o Outlook ou qualquer outra coisa que aparentemente poderiam ter sido causando isso. Ele foi logo controlado para baixo para uma exceção gerenciada lançada por um suplemento gerenciado. Um amigo meu “ Minhas ” refere-se a coluna co-autor Jesse Kaplan — Ed. do Visual Studio Tools for Office (VSTO) equipe — responsável por suplementos gerenciados para Office — foi enviada para diagnosticar esse problema na máquina de um dos vítimas mais proeminentes desse bug: Ray Ozzie, quem foi encarregado chefe técnico no momento.

Uma vez no escritório de Ray meu amigo foi rapidamente capaz de determinar que uma versão beta do .NET Framework 2.0 tinha sido implantada por meio de um programa beta interno e ele identificado qual Office suplemento estava causando o problema. Como uma compatibilidade PMs na equipe do CLR, Instalei o suplemento e levou a partir daí.

Determinamos rapidamente o que aconteceu de errado: o suplemento tinha uma condição de corrida em que ele iniciado nove threads diferentes e após cada uma inicializada os dados de iniciar o thread processados (de consulte do Figura 1). Os codificadores tem sorte com a temporização, mas depois que o .NET Framework 2.0 foi instalado, o suplemento foi automaticamente rolado frente .NET 2.0, por motivos de que eu descrita acima. Mas o .NET 2.0 foi ligeiramente mais rápido em iniciando threads, portanto, a condição de corrida latentes iniciado para superfície consistentemente.

Figura 1 do código a partir do suplemento

Thread [] threads = new Thread[9];
for (int i=0; i<9; i++)
{
    Worker worker = new Worker();
    threads[i] = new ThreadStart(worker.Work);
    threads[i].Start(); //This line starts the thread executing
    worker.identity =i; //This line initializes a value that
                        //the thread needs to run properly
}

Esta falha de aplicativo orientou casa uma lição rígida na compatibilidade: não importa como disco rígido, tentamos evitar fazer alterações de comportamento que pode interromper aplicativos, coisas simples, como um aperfeiçoamento de desempenho pode expor bugs em aplicativos e suplementos que podem causar a falha quando executado em qualquer coisa diferente de runtime que eles foram criados e testados em. Percebemos que não havia uma maneira para nós evoluir a plataforma de qualquer maneira significativa e garantir que aplicativos como um acima podem executar perfeitamente na versão mais recente.

A instalação danificada

Durante nossa testes de compatibilidade podemos veio após um aplicativo que executava bem se .NET 2.0 foi instalado depois da aplicação, mas falha se o aplicativo foi instalado em uma máquina que tinha (versão o aplicativo foi compilado contra) 1.1 e 2.0. Levou um tempo para descobrir o que estava acontecendo, mas podemos controladas problema para baixo até um pouco de código que estava sendo executado dentro o instalador novamente, foi, flutuante frente 2.0 e esta vez tendo problemas para localizar o diretório do framework.

A lógica de detecção foi claramente frágil e realmente errado, como você pode ver aqui:

string sFrameworkVersion = System.Environment.Version.ToString();
string sWinFrameworkPath = session.Property["WindowsFolder"] +
"Microsoft.NET\\Framework\\v" +
sFrameworkVersion.Substring(0,8) + "\\";

Mas mesmo após corrigindo esse bug, o aplicativo ainda Falha ao executar corretamente após a instalação.Aqui está a correção:

string sWinFrameworkPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();

Acontece que o instalador foi olhando para o diretório do framework obter um caminho para caspol.exe e dar permissão de aplicativo para executar dessa estrutura.Interrompeu mesmo após localizar o caminho porque ele tinha apenas próprio permissão concedida para execução no CLR 2.0, mesmo que o próprio aplicativo é executado no CLR 1.1.Aqui está o código do problema:

System.Diagnostics.Process.Start(sWinFrameworkPath + "caspol.exe " + casPolArgs);

Compatibilidade through-Process Side-by-Side

O problema principal causando problemas em todos esses casos, como podemos veio entender, é que era impossível fazer quaisquer alterações significativas ou adições nossa plataforma e ainda assegurar que a versão mais recente poderia executar qualquer aplicativo, bem como versões mais antigas foram.

Desde o início, as classes tentou resolver esse problema por instalações lado a lado suporte de várias versões do framework em uma máquina e tendo cada aplicativo escolha qual versão ela queria executar em.

Infelizmente a limitação do um runtime por processo significava que para gerenciados componentes COM e cenários de extensibilidade, onde havia vários aplicativos independentes em execução no mesmo processo, não havia nenhuma opção única funcionaria para cada um.Essa limitação significada que alguns componentes não foram indo para obter o runtime que eles queriam e que, independentemente de como disco rígido que tentamos manter a compatibilidade, alguns porcentagem deles violaria.

Nossa nova capacidade de carregar várias versões do runtime em um processo resolve esses problemas.

Princípios geral

Para ajudar a entender melhor algumas das decisões que fizemos e o comportamento detalhado que descrevemos posteriormente nesta coluna, é útil discutir os princípios de orientação nós mantidos para enquanto estiver criando esse recurso.

  1. Instalar uma nova versão do .NET Framework não deve ter nenhum impacto em aplicativos existentes.
  2. Devem executar aplicativos e suplementos contra a versão do framework que eles foram criados e testados contra.
  3. Há situações, como quando usando bibliotecas, onde podemos não pode executar código contra a estrutura que as bibliotecas foram criadas contra, portanto, deve ainda almejado para compatibilidade com versões anteriores de 100 por cento.

Todos os aplicativos e suplementos existentes devem continuar a executar contra as versões do framework que eles foram criados e configurados para execução e não devem ver a nova versão, a menos que especificamente peça para ele.Isso sempre foi a regra para aplicativos gerenciados, mas agora também se aplica a suplementos gerenciados e consumidores do runtime APIs de hospedagem.

Para além certificando-se de executar aplicativos contra a versão do runtime que foram criados com, ainda precisamos Verifique se é fácil transição para um tempo de execução mais recente, portanto, podemos ter mantido compatibilidade para o .NET Framework 4 como alta como ou superior que era com o .NET 2.0.

Visão geral do problema

O runtime do .NET Framework 4 — e todas as futuras runtimes — será capaz de executar em processo com outro.Enquanto não fizemos back porta essa funcionalidade para runtimes antigos (1.0 através de 3.5), podemos Certifique-se de que 4 e além poderão executar em processo com qualquer único runtime mais antigo.Em outras palavras, você será capaz de carregar 4, 5 e 2.0 no mesmo processo, mas não poderá carregar 1.1 e 2.0 no mesmo processo..NET 2.0 estruturas através de 3.5 todos executados em runtime 2.0 e assim não ter nenhum conflito com outro, como mostrado no do Figura 2.

.NET framework versão        
  1.1 2.0 por meio de 3.5 4 5
1.1 N/A Não Sim Sim
2.0 por meio de 3.5 Não N/A Sim Sim
4 Sim Sim N/A Sim
5 Sim Sim Sim N/A

Figura 2 tornará esses carga Runtimes no mesmo processo?

Não há componentes ou aplicativos existentes devem observar qualquer diferença quando o runtime do .NET Framework 4 é instalado: eles devem continuar a obter qualquer runtime foram criados contra.Aplicativos e componentes de COM gerenciados criados contra .NET 4 executará no runtime 4.Hosts que desejarem interagir com o runtime 4 precisará especificamente o solicitar.

O que em processo Mean pelo lado para você?

Usuários finais e administradores de sistemas: Agora você pode ter confiança quando você instala uma nova versão do runtime, independentemente ou com um aplicativo, ele não terá impacto na sua máquina e todos os aplicativos existentes continuarão a executar como faziam antes.

Desenvolvedores de aplicativo: Em PROC. SxS quase não tem impacto em desenvolvedores de aplicativo.Aplicativos sempre tem padronizados para executar contra a versão do framework no qual eles foram criados e não foi alterado.A única alteração no comportamento que fizemos impacta desenvolvedores de aplicativos é que nós não mais automaticamente será executado um aplicativo criado contra um runtime mais antigo em uma versão mais recente quando a versão original não está presente.Em vez disso, podemos solicitará o usuário para baixar a versão original e fornecer um link para tornar fácil fazer isso.

Ainda podemos fornecer opções de configuração que permitem que você indicar quais versões do framework que você deseja que seu aplicativo para executar contra, portanto, é possível executar um aplicativo mais antigo em um tempo de execução mais recente, mas não fazemos isso automaticamente.

Desenvolvedores de biblioteca e consumidores: SxS no PROC. não resolve problemas de compatibilidade enfrentados por desenvolvedores de biblioteca.Quaisquer bibliotecas carregadas diretamente por um aplicativo — tanto por meio de uma referência direta ou um Assembly.Load*—will continuar carregar diretamente em runtime e AppDomain do aplicativo carregá-lo.Isso significa que, se um aplicativo é recompilado para executar contra o runtime do .NET Framework 4 e ainda tem assemblies dependentes criados contra .NET 2.0, esses dependentes serão carregado no runtime do .NET 4.Portanto, ainda recomendamos Testando seu 
against bibliotecas todos versão do framework que você deseja dar suporte.Este é um dos motivos que podemos continuaram manter nosso alto nível de compatibilidade com versões anteriores.

Desenvolvedores de componente COM gerenciado: No passado, esses componentes seriam executado automaticamente contra a versão mais recente do runtime instalado na máquina.Agora, pre-.NET Framework 4 componentes ainda irão obter ativados contra o tempo de execução mais recente (3,5 ou anterior) e todos os componentes mais recentes serão carregados contra versão que foram criados, como mostrado no do Figura 3.

       

       

Figura 3 Managed componentes COM e interoperabilidade de Runtime

Desenvolvedores de extensão de shell: Extensão do shell é um nome geral aplicado a uma ampla variedade de pontos de extensibilidade dentro do shell do Windows.Dois exemplos comuns são extensões adicionar o menu de contexto do botão direito do mouse para arquivos e pastas e aqueles que fornecer ícones personalizados ou ícone sobreposições para arquivos e pastas.

Essas extensões são expostas por meio de um modelo COM padrão e sua definição característica é que eles são carregados em processo com qualquer aplicativo.É este último bit e o fato de que apenas um CLR tem sido permitido por processo que causou problemas para extensões do shell gerenciado.Para elaborar:

  • Extensão shell foi escrito contra runtime versão N.
  • Ele precisa ser carregável em qualquer aplicativo na máquina, incluindo aqueles criados contra versões posteriores e anteriores N.
  • Se o aplicativo foi compilado contra uma versão mais recente do que a extensão, coisas são geralmente OK, a menos que haja problemas de compatibilidade.
  • Se o aplicativo foi compilado contra uma versão anterior da extensão, é garantido falha — o runtime antigo obviamente não é possível executar uma extensão de shell foi construída em uma mais recente.
  • Se alguma forma a extensão shell foi carregada antes componentes de código gerenciado do aplicativo, sua escolha de versão do framework poderia entrar em conflito com o aplicativo e quebrar tudo.

Esses problemas levaram nós recomendamos oficialmente contra — e não suporte — o desenvolvimento de extensões do shell no processo usando código gerenciado.Essa foi uma escolha dolorosa para nós e para nossos clientes como você pode ver neste fórum do MSDN explicando o problema: https://social.msdn.Microsoft.com/Forums/en-US/netfxbcl/thread/1428326d-7950-42b4-ad94-8e962124043e.Extensões shell são muito populares e coloca uma última onde os desenvolvedores de certos tipos de aplicativos são forçados a escrever código nativo.Infelizmente, devido a nossa limitação permitindo que apenas um runtime por processo, nós não pôde dar suporte-los.

Com a capacidade de ter vários runtimes no processo com outro runtime, que agora pode oferecemos suporte geral para gravação gerenciados extensões shell — mesmo aqueles que executar em processo com aplicativos arbitrários na máquina.Nós ainda não oferecem suporte à escrita shell usando qualquer versão anterior ao .NET Framework 4 porque essas versões do runtime não carregam extensões em processo com outro e irão causar falhas em muitos casos.

Os desenvolvedores de extensões do shell, gerenciados e nativos, ainda terá que tomar cuidados especiais e garantir que eles são capazes de executar uma ampla variedade de ambientes e funcionam bem com outras pessoas.Como podemos obter mais perto de liberar para produção (RTM), oferecemos orientações e exemplos que ajudarão você a desenvolver extensões shell gerenciado de alta qualidade que jogar bem no ecologicamente sistema do Windows.

Hosts de código gerenciado: Se você hospedar o código gerenciado usando ativação COM nativa, você não terá fazer nada especial para trabalhar com vários runtimes.Você pode simplesmente ativar componentes como sempre fez e o runtime carregá-los acordo com a regras listadas na do Figura 3.

Se você já usou qualquer nosso 4 Framework pre-.NET APIs de hospedagem, provavelmente você tenha notado que todos eles assumem que apenas um runtime nunca será carregado no processo.Portanto, se você hospedar o runtime usando nossas APIs nativas, você precisará modificar seu host para ser in PROC.-SxS-reconhecem.Como parte da nossa nova abordagem de ter vários runtimes em um processo, temos preterido as APIs de hospedagem antigas, única runtime cientes e adicionado um novo conjunto de APIs de hospedagem projetado para ajudar a gerenciar um ambiente multi runtime.MSDN terão a documentação completa para as novas APIs, mas será relativamente fácil de usar se você tiver experiência usando as atuais.

Um dos desafios mais interessantes que podemos enfrentados ao desenvolver-PROC. SxS foi a questão de como atualizar o comportamento das APIs de hospedagem existentes, único runtime cientes.Um intervalo de opções foi disponível, mas quando os princípios a seguir dispostas anteriormente nesta coluna nós foram deixados com as seguintes diretrizes: as APIs deve se comportar de modo que quando o .NET Framework 4 é instalado em uma máquina, o comportamento exato faziam antes que eles retornam.Isso significa que eles podem apenas ser cientes do um runtime em cada processo e que mesmo se você usado de forma que seria ter ativado anteriormente o tempo de execução mais recente na máquina, eles só lhe dará mais recente runtime com uma versão anterior 4.

Ainda existem maneiras “ ligar ” essas APIs para o runtime do .NET Framework 4, passando o número da 4 versão explicitamente a eles ou configurando seu aplicativo de uma determinada maneira, mas, novamente, isso acontecerá somente se você solicitar especificamente o runtime 4 e não se solicitada “ últimas ”.

Em resumo: código usando que as APIs de hospedagem existentes continuarão a funcionar quando o .NET Framework 4 está instalado mas irá obter uma exibição do processo vê apenas um runtime carregado.Além disso, para manter a compatibilidade, eles geralmente poderão interagir somente com versões de pré-4.Detalhes de qual versão é escolhido para cada uma dessas APIs antigos estarão disponíveis no MSDN, mas algumas regras acima devem ajudar a compreender como determinamos esses comportamentos.Se você deseja interagir com vários runtimes, será necessário mover novas APIs.

C + / CLI desenvolvedores: C + / CLI ou C++ gerenciado é uma tecnologia interessante que permite aos desenvolvedores de código gerenciado e nativo no mesmo assembly de misturar e gerenciar as transições entre os dois amplamente sem interação do desenvolvedor.

Devido a arquitetura, haverá limites sobre como usar esses assemblies neste mundo novo.Um dos problemas fundamentais é que, se estamos permitido esses assemblies sejam carregados várias vezes por processo, podemos ainda precisaria manter isolamento entre seções dados gerenciado e nativo.Isso significa que carregando duas vezes, ambas as seções que não é permitido pelo carregador do Windows nativo.Os detalhes completos de por que temos as restrições a seguir estão fora do escopo desta coluna, mas estarão disponíveis em outro lugar como podemos se aproximar RTM.

Restrição básica é pre-.NET baseada no Framework 2.0 C + / CLI assemblies só podem carregar no runtime do .NET 2.0.Se você fornecer um C + 2.0 / CLI biblioteca e quiser que ele seja consumíveis de 4 e depois, você precisa recompilar com cada versão você deseja que ele seja carregado no.Se você consumir uma dessas bibliotecas, será necessário obter uma versão atualizada do desenvolvedor biblioteca ou, como um último recurso, você pode configurar seu aplicativo para bloquear runtimes de pré-4 do seu processo.

Não há mais incômodo

O Microsoft .NET Framework 4 é a versão mais compatível com versões anteriores do .NET ainda.Trazendo-PROC. SxS para a tabela, a Microsoft garante que ação simples de instalar .NET 4 não quebrará qualquer aplicativo existente e que tudo já instalado na máquina funcionará, bem como fez antes.

Os usuários finais não terá mais se preocupar que a estrutura instalando — diretamente ou com um aplicativo que requer a ele — quebrará qualquer dos aplicativos já na máquina.

Empresas e profissionais de TI podem adotar novas versões do framework como rapidamente ou gradualmente desejarem sem precisar se preocupar com diferentes versões usadas por aplicativos diferentes em conflito com outro.

Os desenvolvedores podem usar a versão mais recente do framework para criar seus aplicativos e poderão reassure seus clientes que irá ser seguros implantar.

Finalmente, hosts e desenvolvedores de suplemento podem ser confortáveis sabendo que eles obterão a versão do framework que deseja, sem afetar qualquer outra, para que elas possam ser certeza que seu código irá continuar trabalhando, até mesmo como novas versões do framework são instaladas.                                                             

Jesse Kaplan  é o gerente do programa de interoperabilidade gerenciada/nativo para equipe de CLR da Microsoft. Sua passado responsabilidades incluem compatibilidade e extensibilidade.

Luiz Santos*, anteriormente parte da equipe do CLR, é um gerente de programa na equipe conectividade SQL, onde é responsável por provedores ADO.NET gerenciado, incluindo SqlClient, ODBCClient e OLEDBClient.*

Graças aos seguintes especialistas técnicos para revisão deste artigo: Joshua Goodman, Simon Hall e Sílvio Selitrennikoff