Подтвердить что ты не робот

Как обновить сборку для запущенного процесса С# (быстрое развертывание AKA)?

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

Подводя итог; как я могу обновить код во время использования .exe?

4b9b3361

Ответ 1

Это легко сделать. Вы можете переименовать файл, Windows имеет блокировку на дескрипторе, а не запись каталога для файла. Теперь вы можете просто скопировать обновление без проблем. Все, что осталось сделать, это избавиться от переименованного файла после того, как приложение снова запустится. При необходимости.

Ответ 2

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

Ответ 3

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

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

Ответ 6

Как насчет следующего:

  • Разверните exe в папку обновлений.
  • Всякий раз, когда приложение запускается, оно проверьте папку обновлений.
  • Если он не пуст, выполните копию Программа
  • Затем программа копирования заменит существующий exe с одним в папка обновления
  • Удалить что-либо в папке обновления
  • Затем перезапустите exe

Ответ 7

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

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

  • Скопируйте новую dll в подпапку где-нибудь
  • Добавьте команду командной строки xcopy в раздел реестра RunOnce, чтобы скопировать новую dll из подпапки в конечную папку exe, где вы хотите это пойти.
  • Reboot.

В RunOnce содержатся команды командной строки, которые запускаются после перезагрузки, а затем удаляются из реестра, поэтому они не запускаются снова. Именно так InstallShield позволяет вам перезаписать определенную DLL, когда они используются другими приложениями.

Ответ 8

Этот класс переименует исполняемый исполняемый файл, если он завершен без исключения, вы можете просто написать новый исполняемый файл, а затем перезапустить, например:

Ourself.Rename();
// Download or copy new version
File.Copy(newVersion, Ourself.FileName());
// Launch new version
System.Diagnostics.Process.Start(Ourself.FileName());
// Close current version
Close(); // Exit();

Достаточно легко?

class Ourself
{
    public static string FileName() {
        Assembly _objParentAssembly;

        if (Assembly.GetEntryAssembly() == null)
            _objParentAssembly = Assembly.GetCallingAssembly();
        else
            _objParentAssembly = Assembly.GetEntryAssembly();

        if (_objParentAssembly.CodeBase.StartsWith("http://"))
            throw new IOException("Deployed from URL");

        if (File.Exists(_objParentAssembly.Location))
            return _objParentAssembly.Location;
        if (File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName))
            return System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName;
        if (File.Exists(Assembly.GetExecutingAssembly().Location))
            return Assembly.GetExecutingAssembly().Location;

        throw new IOException("Assembly not found");
    }

    public static bool Rename()
    {
        string currentName = FileName();
        string newName = FileName() + ".ori";
        if (File.Exists(newName))
        {
            File.Delete(newName);
        }
        File.Move(currentName, newName);
        return true;
    }
}