Как обновить ваш exe с удаленного хоста - c # 4.0 - wpf application - PullRequest
1 голос
/ 07 декабря 2011

Я хочу обновить свой exe с удаленного сервера. Поэтому, когда кнопка нажата на моем wpf-приложении, оно загрузит удаленный, а также удаленный текстовый файл и заменит текущие файлы в той же папке, в которой работает exe. Таким образом, он будет перезаписывать текущий TXT и и EXE-файл, в то время как мой исполняемый файл работает. Как я могу достичь этого?

URL-адрес удаленного хоста www.mydomain.com/MyAPP.exe

приложение wpf, c # 4.0

Ответы [ 3 ]

2 голосов
/ 07 декабря 2011

Решение зависит от вашего конкретного случая.Но нет прямого решения, потому что вы не можете обновить сборки, пока они загружены в память и используются.Я могу предложить 2 решения: использовать теневое копирование и использовать некоторый вспомогательный исполняемый файл.Я использовал оба из них.

Теневое копирование.

Очевидный способ - сделать основной исполняемый файл для теневого копирования, заменить его во время работы приложения.а затем перезапустите приложение.Но вы не можете сделать домен приложения по умолчанию теневым копированием, могут быть только вторичные домены приложений.Но вы все равно можете переместить весь свой код в другую сборку (скажем, MainAppLib.dll) и переписать исполняемый файл основного приложения (MainApp.exe), чтобы он содержал только «код загрузчика».Этот код загрузчика должен создать другой домен приложения, установить его для теневого копирования и затем запустить логику вашей программы в дополнительном домене приложения.Не допускайте прямых ссылок из основного домена приложения на MainAppLib.dll, потому что тогда эта сборка будет загружена в основной домен приложения, который не является теневым копированием, и файл сборки будет заблокирован.В большинстве случаев вы можете использовать методы AppDomain.ExecuteAssembly () .

Исполняемый файл-помощник

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

ps Лично я предпочитаю первое решение, потому что оно включает в себя магию вуду с использованием доменов приложений, отражений, сборок и т. Д. И его можно развить виспользуя плагины, если вам нужно (например, через MEF framework ).Но последнее легче понять, особенно если вы никогда не работали с доменами приложений и загрузкой сборок вручную, это довольно просто.

2 голосов
/ 07 декабря 2011

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

«Настоящая» исполняемая программа хранится в подкаталоге этого исходного приложения.Когда приложение оболочки запускается, после того как оно загрузило и установило какие-либо обновления для реального приложения, оно запускает исполняемый файл реального приложения в отдельном домене приложений.

Вот ядро ​​«реального» приложения, запускаемого изприложение оболочки:

        System.AppDomainSetup oSetup = new System.AppDomainSetup();
        string sApplicationFile = null;

        // Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
        oSetup.ShadowCopyFiles = "true";
        oSetup.ApplicationName = sAppName;

        // Generate the name of the DLL we are going to launch
        sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");

        oSetup.ApplicationBase = sApplicationDirectory;
        oSetup.ConfigurationFile = sApplicationFile + ".config";
        oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;

        // Launch the application
        System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
        oAppDomain.SetData("App", sAppName);
        oAppDomain.SetData("User", sUserName);
        oAppDomain.SetData("Pwd", sUserPassword);

        oAppDomain.ExecuteAssembly(sApplicationFile);

        // When the launched application closes, close this application as well
        Application.Exit();

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

1 голос
/ 07 декабря 2011

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

...