Внутрипроцессное параллельное выполнение
Примечание.
Эта статья относится к .NET Framework. Он не применяется к более новым реализациям .NET, включая .NET 6 и более поздние версии.
Начиная с .NET Framework 4, разработчики могут использовать внутрипроцессное параллельное размещение для запуска нескольких версий среды CLR в одном процессе. Управляемые COM-компоненты по умолчанию выполняются в той версии платформы .NET Framework, в которой они были созданы, вне зависимости от загруженной для процесса версии .NET Framework.
Общие сведения
Платформа .NET Framework всегда предоставляла возможность параллельного размещения для приложений с управляемым кодом, но до появления версии .NET Framework 4 эта функция не была доступна для управляемых COM-компонентов. Загруженные в процесс COM-компоненты в прошлом выполнялись в уже загруженной версии среды выполнения или в последней установленной версии платформы .NET Framework. Если эта версия была несовместима с COM-компонентом, то выполнение завершалось ошибкой.
Платформа .NET Framework 4 предоставляет новый подход к параллельному размещению, который обеспечивает выполнение следующих требований:
Установка новой версии платформы .NET Framework не повлияет на существующие приложения.
Приложения будут выполняться в той версии платформы .NET Framework, в которой они были построены. Новая версия платформы .NET Framework не используется, если явным образом не указано иное. В то же время приложения легче перевести на использование новой версии платформы .NET Framework.
Влияние на пользователей и разработчиков
Конечные пользователи и системные администраторы. Эти группы пользователей теперь могут быть уверены, что установка новой версии среды выполнения (отдельно или вместе с приложением) не окажет влияния на работу компьютера. Существующие приложения будут выполняться, как раньше.
Разработчики приложений. Параллельное размещение не затрагивает разработчиков приложений. Приложения по умолчанию всегда выполняются в версиях платформы .NET Framework, в которых они были созданы. Это поведение не изменено. Разработчики могут переопределить это поведение и настроить приложение на выполнение в более новой версии платформы .NET Framework (см. сценарий 2).
Разработчики и пользователи библиотек. Параллельное размещение не устраняет проблемы совместимости, с которыми сталкиваются разработчики библиотек. Библиотека, загруженная приложением напрямую (через прямую ссылку или с помощью вызова Assembly.Load) продолжает использовать среду выполнения класса AppDomain, в который она загружена. Следует проверить корректность работы библиотек со всеми версиями платформы .NET Framework, поддержка которых необходима. Если приложение компилируется с помощью среды выполнения .NET Framework 4, но содержит библиотеку, построенную с помощью более старой среды выполнения, эта библиотека также будет использовать среду выполнения .NET Framework 4. Но, если приложение было создано с помощью более старой среды выполнения и библиотеки, которая построена в .NET Framework 4, приложение также необходимо явным образом настроить на использование .NET Framework 4 (см. сценарий 3).
Разработчики управляемых COM-компонентов. Управляемые COM-компоненты ранее автоматически выполнялись в последней версии среды выполнения, установленной на компьютере. Теперь COM-компоненты можно запускать в той версии среды выполнения, в которой они были созданы.
Как отражено в следующей таблице, созданные на платформе .NET Framework версии 1.1 компоненты могут запускаться параллельно с компонентами версии 4, но не могут выполняться вместе с компонентами версий 2.0, 3.0 или 3.5, так как параллельное размещение для этих версий невозможно.
Версия платформы .NET Framework 1,1 2.0 - 3.5 4 1,1 Нет данных No Да 2.0 - 3.5 No Нет данных Да 4 Да Да Неприменимо
Примечание.
Версии платформы .NET Framework 3.0 и 3.5 созданы с помощью инкрементального построения на базе версии 2.0 и не требуют параллельного запуска. По сути они представляют собой одну и ту же версию.
Общие сценарии параллельного размещения
Сценарий 1. Собственное приложение, которое использует COM-компоненты, созданные в более ранних версиях платформы .NET Framework.
платформа .NET Framework версии, установленные: платформа .NET Framework 4 и все остальные версии платформа .NET Framework, используемые com-компонентами.
Необходимые действия: в этой ситуации не следует предпринимать никаких действий. COM-компоненты будут выполняться в той версии платформы .NET Framework, в которой они были зарегистрированы.
Сценарий 2. Управляемое приложение, созданное с помощью платформа .NET Framework 2.0 с пакетом обновления 1 (SP1), которое вы предпочитаете запускать с платформа .NET Framework 2.0, но готовы работать на платформа .NET Framework 4, если версия 2.0 отсутствует.
платформа .NET Framework версии, установленные: более ранняя версия платформа .NET Framework и платформа .NET Framework 4.
Что делать: в файле конфигурации приложения в каталоге приложения используйте <элемент запуска> и поддерживаемый< набор элементовRuntime> следующим образом:
<configuration> <startup > <supportedRuntime version="v2.0.50727" /> <supportedRuntime version="v4.0" /> </startup> </configuration>
Сценарий 3. Собственное приложение, использующее com-компоненты, созданные с более ранними версиями платформа .NET Framework, которые требуется запустить с помощью платформа .NET Framework 4.
платформа .NET Framework версии, установленные: платформа .NET Framework 4.
Необходимые действия: откройте файл конфигурации приложения в каталоге приложения и используйте элемент
<startup>
, атрибутuseLegacyV2RuntimeActivationPolicy
которого имеет значениеtrue
, и набор элементов<supportedRuntime>
следующим образом:<configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" /> </startup> </configuration>
Пример
В следующем примере показан неуправляемый узел COM, в котором управляемый COM-компонент выполняется с помощью версии платформы .NET Framework, для которой был предназначен данный компонент.
Чтобы выполнить следующий пример, скомпилируйте и зарегистрируйте следующий управляемый COM-компонент с помощью платформа .NET Framework 3.5. Чтобы зарегистрировать компонент, в меню Проект выберите пункт Свойства, перейдите на вкладку Сборка, а затем установите флажок Регистрация для 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);
}
}
}
Скомпилируйте следующее неуправляемое приложение C++, которое активирует COM-объект, созданный в предыдущем примере.
#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;
}