Обновление библиотеки DLL в GAC, содержащей страницы aspx для веб-приложения - PullRequest
1 голос
/ 19 апреля 2009

Прости меня, кодер, потому что я согрешил. Я поместил некоторый код в dll в GAC, и теперь я озадачен тем, как GAC действительно работает с IIS.

В нашей среде интрасети у меня есть несколько связанных веб-приложений (около 10). Каждое приложение запускается из отдельного URL-адреса и потенциально запускается в своем собственном пуле приложений. На данный момент все приложения находятся на одном сервере, но это не обязательно. Эта настройка позволяет нам контролировать, разрабатывать и переносить каждое приложение отдельно. Однако есть несколько частей каждого приложения, которые мы хотели бы использовать во всех наших приложениях (главные страницы, страницы входа, меню и т. Д.). Запрос от руководства состоял в том, что изменения в этих файлах могут быть универсальными и вступать в силу без необходимость перекомпиляции и перенастройки каждого веб-приложения. Есть много способов выполнить эту задачу, и, несмотря на предупреждения об избежании GAC, это действительно выглядело как случай, когда использование поставщика виртуального пути и DLL, хранящихся в GAC, имело смысл.

Я собрал провайдера Virtual path, а затем внедрил файлы и ресурсы, которые мне нужны, чтобы быть общими в DLL. (Я мог бы заставить VPP извлекать файлы из базы данных, но я надеялся, что встраивание файлов в саму dll будет более производительным.

Осложнение # 1

Я не хотел, чтобы разработчикам каждого приложения приходилось связываться с их собственным GAC для тестирования и запуска их приложения, поэтому в каждое решение я просто включил проект провайдера виртуальных путей и сделал его результат dll, скопируйте локально, (а также строго названный), это означает, что dll провайдера вместе со своими внедренными файлами копируются в каталог bin приложения. Пока разработчик не имеет версию этого dll в своем GAC (что они не должны), используется локальная копия bin. Это позволяет разработчику легко изменять и тестировать как файлы приложения, так и файлы, которые являются общими для каждого приложения. Это также означает, что, если это не было намеренно предотвращено, общие dll будут существовать в каталоге bin каждого приложения в производстве. Однако, поскольку IIS всегда будет использовать версию GAC, если она существует, даже если локальная версия устарела, версия GAC всегда используется.

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

Осложнение № 2

На самом деле кодирование приложения таким образом, чтобы оно всегда использовало последнюю версию библиотеки DLL вместо конкретной версии, с которой оно было скомпилировано, кажется довольно сложным делом. (Мне еще не удалось найти хороший пример того, как это сделать, но я думаю, что мне понадобится цепочка политик издателя.) Казалось, гораздо проще попробовать более очевидный ответ - оставить номер версии dll неизменным при переносе нового версия VPP dll для GAC. Казалось, это работало нормально, пока не получилось.

Используя Windows / оснастку сборки на сервере, я заменил более старую версию v. 1.0.0.0 моей библиотеки DLL в GAC обновленной копией v. 1.0.0.0. Хотя я обновил dll в GAC, мои приложения продолжали использовать старую версию кода. Перезапуск IIS и даже полная перезагрузка сервера, похоже, не помогли. Что меня по-настоящему удивило, так это то, что в конечном итоге IIS загадочно и неожиданно исправит себя и начнет использовать правильную копию dll из GAC.

Я видел много связанных с GAC вопросов такого типа, которые, казалось, заканчивались тем, что «вдруг мой веб-сайт снова начал работать правильно». Мне потребовалось некоторое время, чтобы понять, что это было следствием того, что IIS кэшировал мою строго названную dll, и что я неправильно использовал способ, которым строго названные dll должны были работать.

Далее я попробовал гвыбрав версию dll из GAC полностью. Поскольку в каталоге bin все еще была копия моей dll, я ожидал, что процесс либо завершится с ошибкой, либо вернется / продвигается к версии, которая была в каталоге bin. Однако, поскольку версия в корзине была также 1.0.0.0, IIS продолжал использовать кэшированную копию библиотеки DLL, которой теперь больше не было на компьютере. (Это на какое-то время меня действительно расстроило, потому что я потерял уверенность в том, что GAC версия вообще работала)

Наконец, единственный способ, которым я должен был обязательно получить dll для обновления, - это удалить копию dll из GAC, удалить копию dll из каталога bin, запустить сайт, чтобы он вышел из строя, а затем Поместите новую версию DLL в GAC. Запуск и остановка IIS во время этого не имели никакого эффекта. Это постоянно заставляло мои приложения использовать новый код, но…

Так много для того, чтобы просто вставить новую версию dll в GAC и обеспечить беспрепятственное распространение ее новых эффектов.

После прочтения некоторых смежных вопросов я пытаюсь:

  1. Остановка IIS
  2. Обновление программного обеспечения библиотеки DLL в GAC (но при этом номер версии остается новая dll на 1.0.0.0)
  3. удаление всего в «C: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 \ Temporary Папка ASP.NET Files (я так думаю вызывает перекомпиляцию, но это кувалда починки)
  4. перезагрузите IIS.

Кажется, это работает, но все же кажется, что что-то не так с необходимостью идти на все эти неприятности. Есть ли более простой способ заставить IIS использовать текущий экземпляр DLL GAC? Есть ли лучший способ добиться эффекта, которого я добиваюсь. (некоторые распространенные файлы .aspx и .xml открывают общий доступ к различным приложениям, которые можно обновлять отдельно от самих приложений.)

Редактировать: на основе комментария от шахкальпеша я нашел эту страницу в Microsoft
http://msdn.microsoft.com/en-us/library/7wd6ex19(VS.80).aspx

Это включало в себя этот маленький кусочек знания:

Перенаправление версий сборки Чтобы перенаправить одну версию в другую, используйте элемент <bindingRedirect>. Атрибут oldVersion может указывать либо одну версию, либо диапазон версий . Например, <bindingRedirect oldVersion="1.1.0.0-1.2.0.0" newVersion="2.0.0.0"/> указывает, что среда выполнения должна использовать версию 2.0.0.0 вместо версий сборки между 1.1.0.0 и 1.2.0.0.

Что означает, что вместе с моей dll я мог выдвинуть один файл политики издателя, в котором все перенаправлено до последней версии. Такого рода смягчение того, что я считал кошмарной цепочкой политик, где мне приходилось поддерживать связь от каждой возможной версии до самой последней ...

Я попробую это и посмотрю, запускает ли обновление, подобное этому, также IIS, чтобы использовать правильную версию нового файла (после сброса пула приложений)

Ответы [ 3 ]

2 голосов
/ 20 апреля 2009

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

В этом случае это http://msdn.microsoft.com/en-us/library/eftw1fys(VS.71).aspx может помочь.

0 голосов
/ 22 сентября 2009

Чтобы вам было проще - мы делали очень похожую вещь с нашими общими сборками в течение многих лет.

Что следует помнить при использовании GAC:

  1. Если вы собираетесь заменить существующую версию DLL на тот же номер версии - вы должны УДАЛИТЬ предыдущую версию первой (либо удалить из c: \ windows \ assembly, либо GACUtil /u ) - просто его повторное развертывание / GACUtil / etc не будет иметь никакого эффекта - он думает, что DLL уже существует и не обновляет ее.
  2. Имея в виду 1, проще просто увеличить номера версий и, как вы обнаружили, добавить BindingRedirect где-нибудь в цепочке конфигурации, обычно мы используем Machine.Config, поскольку хотим влиять на все приложения на серверах.
0 голосов
/ 20 апреля 2009

Помните, что версия ассемблера и версия файла различны .. и, возможно, попробуйте прочитать их как совершенно НОВУЮ версию и вместо этого ссылаться на ЭТО (не 1.0.0.0).

...