Замена файлов .dll во время работы приложения?

18

У меня есть несколько игровых серверов, которые используют определенный файл .dll для запуска. Иногда мне нужно обновить игровые серверы, но я не хочу прерывать игры, которые уже запущены.

Есть ли способ заменить файл .dll (он заблокирован Windows), чтобы следующие экземпляры игровых серверов, которые используют этот файл, открывали новую версию, а старые продолжали использовать старую версию этого .dll до тех пор, пока они не будут перезапущены? ?

Безопасно ли просто разблокировать файл с помощью одного из тех инструментов, которые это делают, и заменить его?


источник
Возможно, не ваша игра. Однако Chrome делает обновление , не прерывая процесс. К сожалению, это зависит от приложения. (Перейдите, %LocalAppData%\Google\Chrome\Applicationи вы увидите папки, в 26.0.1410.64которых хранятся библиотеки DLL разных версий)
Alvin Wong
В зависимости от рассматриваемого программного обеспечения может быть возможно установить и запустить два или более отдельных экземпляра (в разных местах). Неэффективно, но, возможно, работоспособно.
Гарри Джонстон

Ответы:

23

На самом деле, вы можете, и это обычно работает без каких-либо проблем (хотя и не всегда)

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

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

Stephane
источник
11

Нет. Несмотря на то, что DLL может быть полностью отображена в физической памяти во время работы приложения, это точно не гарантируется. Части DLL (и даже исполняемые файлы) могут быть отображены в ОЗУ, в то время как другие ее части остаются на диске и могут быть прочитаны позднее.

Изменение файла на диске, в то время как в Windows есть биты, отображенные в ОЗУ, закончится неудачно. Windows блокирует это по уважительной причине.

Изменить: мне нужно кое-что прояснить, так как некоторые люди, похоже, намерены обвинить Windows в том, что на самом деле проблема дизайна приложения , а не проблема дизайна ОС.

Вы можете обновить библиотеки DLL, используемые приложениями в Windows, не прерывая процесс, но приложение должно быть написано таким образом, чтобы можно было сигнализировать о выгрузке сборки, дождаться завершения обновления, а затем перезагрузить библиотеку DLL. Это не имеет ничего общего с операционной системой, которую вы используете. Это проблема дизайна приложения.

Изменить: Также см. Ответ Стефана о возможном решении, которое может работать, в зависимости от того, как ваше конкретное приложение реагирует на изменение своей DLL. Я думаю, что он заслуживает голоса.

Райан Райс
источник
Есть ли способ переместить этот файл во временное местоположение, чтобы его можно было удалить позже, при этом поместив новый файл в его старое местоположение (чтобы серверы, которые запускаются после этого, использовали новую DLL)? Или дескриптор файла связан с расположением файла?
Это полностью зависит от того, как написано приложение / как оно использует библиотеки DLL. Посмотрите на ответ Грега Аскью. Если дескриптор файла открыт, вы ничего не можете с этим поделать. Вы можете принудительно закрыть дескриптор файла, но вы почти наверняка сломаете, по крайней мере, ваше приложение, если не всю ОС.
Райан Райс
Так что же это за «хорошая причина»? Пока что ваш ответ не содержит убедительной причины, по которой Microsoft не предлагает возможность горячей замены.
Конрад Рудольф
2

Нет, вы не должны возиться с существующими файловыми дескрипторами.

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

/programming/7147577/programmatics-rename-open-file-on-windows .

Грег Аскью
источник
2
По моему опыту, в большинстве случаев (ну, более половины времени, во всяком случае) вы можете переименовывать (но не удалять) DLL без каких-либо изменений в приложении.
Гарри Джонстон
@HarryJohnston: Да, похоже, я могу переименовать .dll, даже если он используется. Я думаю, что я буду делать это с этого момента.
1

Нет, к сожалению, это невозможно.

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

Данила Ладнер
источник
1

Вы можете посмотреть, как работает процесс, размещенный на asp.net, и разработать нечто подобное.

Он берет целое веб-приложение и перемещает его во временное место, из которого приложение фактически загружается. Затем он оставляет процесс для отслеживания изменений в исходной папке, при обнаружении он запускает новый экземпляр приложения в новом временном расположении и начинает перенаправлять новые запросы в это приложение. Затем старое приложение сносится, когда ожидающие запросы завершены.

(Да, это упрощенное представление, в большинстве случаев IIS ставит запросы в очередь до тех пор, пока новое приложение не сможет их взять на себя)

Томас Джеймс
источник
0

Около десяти лет назад я был счастливым пользователем http://www.eggcentric.com/ISAPILoader.htm, который делал обмен dll в IIS ISAPI. Мистер Эгг все еще поддерживает свое решение FOSS.

jkellydresser
источник
0

Установщик NSIS имеет одну опцию, например «Переместить во временную папку» при перезапуске компьютера, ОС помечает некоторый файл для перемещения в другое место при следующей загрузке, при следующей загрузке компьютера эти помеченные файлы автоматически перемещаются в новое местоположение, выбранное ранее. Небольшой поиск по этому вопросу сделает вас счастливыми в этом отношении.

Шашанк Кандхаве
источник
Вы могли бы предоставить полный ответ в своем ответе, вместо того, чтобы указывать ОП на поиск решения. Его бы здесь не спрашивали, нашел ли он уже решение. Благодарю.
Джон aka hot2use