Скомпилируйте независимую от версии DLL в .NET

Сценарий

У меня есть две оболочки для Microsoft Office, одна для 2003 и одна для 2007. Поскольку две версии Microsoft Office, работающие бок о бок, «официально не возможны» и не рекомендуются Microsoft, у нас есть две оболочки: одна с Office 2003, а другая с Office 2007. Мы компилируем обертки отдельно. Библиотеки DLL включены в наше решение, каждая ячейка имеет извлечение такой же, но с "выгруженным" Office 2003 или 2007, поэтому он не пытается скомпилировать эту конкретную DLL. В противном случае при компиляции будут возникать ошибки из-за недоступности библиотек DLL Office COM.

Мы используем .NET 2.0 и Visual Studio 2008.

Факты

Поскольку Microsoft загадочным образом изменила API Office 2003 в 2007 году, переименовав и изменив некоторые методы (вздох), что сделало их несовместимыми с обратной связью, мы необходимость две оболочки. У нас есть каждая машина сборки с решением и одна активированная библиотека Office. Например: на компьютере с Office 2003 выгружена DLL "Office 2007", поэтому она не компилируется. Другая коробка - та же идея, но наоборот. Все это потому, что для программирования не может быть двух разных Office в одной коробке. (технически вы можете иметь два Office вместе, согласно Microsoft), но нет для программирования и не без некоторых проблем.

Проблема

Когда мы меняем версию приложения (например, с 1.5.0.1 на 1.5.0.2), нам нужно перекомпилировать DLL, чтобы она соответствовала новой версии приложения, это происходит автоматически, поскольку оболочка Office включена в решение. Поскольку оболочки содержатся в решении, они наследуют версию приложения, но мы должны сделать это дважды, а затем «скопировать» другую DLL на машину, которая создает установщик. (Боль…)

Вопрос

Можно ли скомпилировать DLL, которая будет работать с версией приложения Любые, несмотря на то, что она «старая»? Я кое-что читал о манифестах, но мне никогда не приходилось с ними взаимодействовать. Будем признательны за любые указатели.

Секретная причина этого заключается в том, что мы не меняли наши оболочки за «века», как и Microsoft с их древними API, но мы перекомпилируем DLL, чтобы она соответствовала версии приложения в выпуске каждый, который мы делаем. Я хотел бы автоматизировать этот процесс вместо того, чтобы полагаться на машины два.

Я не могу удалить DLL из проекта (ни один из них), потому что есть зависимости.

Я мог бы создать третью «мастер-обертку», но еще не думал об этом.

Есть идеи? Кто-нибудь еще с таким же требованием?

Обновлено

Уточнение:

У меня есть 1 решение с N проектами.

«Приложение» + Office11Wrapper.dll + Office12Wrapper.dll.

Обе «оболочки» используют зависимости для приложения + других библиотек в решении (уровень данных, бизнес-уровень, фреймворк и т. д.)

Каждая оболочка имеет ссылки на соответствующий пакет Office (2003 и 2007).

Если я компилирую и не установил Office 12, я получаю ошибки от Office12Wrapper.dll, не находя библиотеки Office 2007. Итак, у меня есть две строительные машины, одна с Office 2003, одна с Office 2007. После полного обновления SVN + компиляции на каждой машине мы просто используем office12.dll в «установщике», чтобы оболочка скомпилировалась с «той же самой». код той же версии ".

Примечание. Машина сборки Office 2007 имеет "выгруженную" оболочку для Office 2003 и наоборот.

Заранее спасибо.

Я исправил ссылку в своем ответе, которая указывает на статью MS о том, как установить два рядом.

HTTP 410 11.11.2008 00:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
1
9 029
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Просто подумайте - можете ли вы использовать TlbExp для создания двух сборок взаимодействия (с разными именами и сборками) и использовать интерфейс / фабрику для кодирования двух через свой собственный интерфейс? Если у вас есть interop dll, вам не нужна COM-зависимость (за исключением, конечно, тестирования и т. д.).

TlbImp имеет / asmversion для версии, поэтому это можно сделать как часть сценария сборки; но я уверен, что вам это даже нужно: просто убедитесь, что "конкретная версия" неверна в ссылке (обозреватель решений)?

Также - я знаю, что это не помогает, но C# 4.0 с dynamic и / или «No PIA» могут здесь помочь (в будущем; возможно).

Спасибо, Марк, я тоже попробую. Я устал от двух строительных коробок. ;)

Martin Marconcini 10.11.2008 22:48

Я не уверен, что полностью следую всему, что вы сказали, но позвольте мне попробовать:

Похоже, у вас есть одно решение с 2 (?) Проектами. Одно - это собственное приложение, а другое - оболочка для Office API. Тогда ваше приложение будет иметь ссылку на проект вашей оболочки Office API. Я никогда раньше не занимался программированием для офиса, но похоже, что программные API-интерфейсы являются обычным компонентом, у вас может быть только одна версия на машине (например, 2003 или 2007, но не обе). И, возможно, здесь проблема, но поскольку у вас есть ссылка на проект, оболочка будет сначала скомпилирована, скопирована в каталог bin вашего приложения, где ваше приложение будет связано с этой сборкой оболочки. Это приведет к тому, что манифест приложения будет специально запрашивать эту версию оболочки во время выполнения.

Если бы у вас была оболочка в отдельном решении и вы добавили ссылку на скомпилированную библиотеку, а не на проект, вы всегда связали бы свое приложение с этой версией оболочки, и вы могли бы избежать проблемы.

Другой возможный выбор - перенаправление привязки сборки. Это более продвинутый вариант и имеет собственный набор проблем, но вы можете прочитать об этом здесь.

Или, аналогично идее Марка, вы можете извлечь интерфейс и вытащить некоторые общие объекты в библиотеку Framework, а также закодировать свое приложение в соответствии с интерфейсом и общими объектами. Затем во время выполнения используйте отражение, чтобы загрузить сборку и создать экземпляр нужной оболочки.

Я думаю, что главное в том, чтобы удалить зависимость проекта, если это возможно. Похоже, оболочка довольно стабильна и не меняется, иначе вы бы не просили ссылку на ее предыдущую версию.

Это близко, но неверно. ;) У меня есть одно решение с тремя проектами (ну больше, но актуально ...). Фактическое приложение и OfficeWrapper11.dll и OfficeWrapper12.dll. Я изучу твои идеи. ты.

Martin Marconcini 10.11.2008 22:40

Параллельная установка Office 2003 и 2007 на одном компьютере определенно возможно - мы делаем это в нашей организации даже на рабочих станциях конечных пользователей.

В этой связанной статье Microsoft рекомендует не делать этого на практике. Но в вашем случае это похоже на одну машину сборки, т.е. вы не собираетесь использовать на ней ни одну из версий Office. В этом контексте я бы попытался посмотреть, сможете ли вы заставить работать параллельную установку.

Мое предположение может быть неверным, и вы пытаетесь сделать это для каждой машины разработчика. В таком случае игнорируйте этот ответ :-)

Я действительно не пробовал, но только предположил, что немного погуглил. Я думаю, что один из способов избежать прикосновения к рабочему коду - это попробовать установить оба офисных пакета, от старых к более новым. (Первый 2003 год, второй 2007 год). Спасибо, я тоже попробую.

Martin Marconcini 10.11.2008 22:47
Ответ принят как подходящий

Когда распознаватель сборок .NET не может найти сборку, на которую указывает ссылка, во время выполнения (в этом случае он не может найти конкретную версию DLL оболочки, с которой было связано приложение), его поведение по умолчанию - сбой и, по существу, сбой приложения. Однако это поведение можно изменить, подключив событие AppDomain.AssemblyResolve. Это событие запускается всякий раз, когда указанная сборка не может быть найдена, и дает вам возможность заменить отсутствующую сборку другой (при условии, что они совместимы). Так, например, вы можете заменить более старую версию DLL-оболочки, которую загружаете сами.

Лучший способ, который я нашел для этого, - добавить статический конструктор в основной класс приложения, которое перехватывает событие, например:

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}

Помещая это в статический конструктор основного класса приложения, он гарантированно запускается до того, как какой-либо код попытается получить доступ к чему-либо в DLL-оболочке, гарантируя, что ловушка будет на месте раньше времени.

Вы также можете использовать файлы политики для перенаправления версий, но это, как правило, более сложно.

Не могли бы вы вкратце объяснить или дать мне направление, как реализовать это с помощью файлов политик? Я сейчас пытаюсь решить проблемы при обновлении до более новой версии dll (см. stackoverflow.com/questions/30165393/…)

Vortex852456 11.05.2015 18:46

У меня проблема с использованием этого решения. Статический код не запускается до разрешения dll. Откуда я это знаю? Я попытался выбросить исключение в статическом инициализаторе, но все же разрешение dll - единственное появляющееся исключение. Однако, если есть библиотеки DLL, я вижу свое исключение.

Jarekczek 09.07.2016 13:31

Решено путем создания основного метода оболочки, который вызывает исходный метод Main. См. Также: Перенаправление сборочных нагрузок во время выполнения

Jarekczek 09.07.2016 14:46

Хорошая розыск! Я просто собрал реализацию, основанную на концепции, представленной выше, и она прекрасно работает:

static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
     string partialName = args.Name.Substring(0, args.Name.IndexOf(','));
     return Assembly.Load(new AssemblyName(partialName));
}

Конечно, есть возможности для улучшения, но это помогает мне!

Другие вопросы по теме