Най-добра практика за писане на самоактуализираща се услуга на Windows [затворено]

Трябва да създадем услуга за Windows, която има способността да се самоактуализира.

Три варианта изникват на ум,

  1. втора услуга, която управлява извличането, деинсталирането и инсталирането на първата услуга.

  2. Използване на рамка на трета страна (предложенията са добре дошли. Вярвам, че .NET поддържа автоматично актуализиране за приложения на Windows Forms, но не и услуги на Windows)

  3. Използване на модел на плъгин, при който услугата е просто обвивка, съдържаща логиката за актуализиране и изпълнение, а бизнес логиката на услугата се съдържа в DLL, който може да бъде заменен.

Може ли някой да хвърли малко светлина върху решението на този проблем?

Благодаря


person Ben Aston    schedule 22.10.2009    source източник


Отговори (3)


Google има рамка с отворен код, наречена Omaha, която прави точно това, което описва вашата точка 1. Той работи като планирана задача на Windows във фонов режим, извън приложенията, които управлява. Google използва Omaha за автоматично актуализиране на своите Windows приложения, включително Chrome. Тъй като идва от Google и тъй като е инсталиран на всяка машина с Windows, която работи с Chrome, Omaha е изключително мощен.

Има статия онлайн, която обяснява в повече подробно как Omaha може да се използва за актуализиране на услуги на Windows. Той твърди, че Omaha е особено подходящ за услуги (срещу, да речем, GUI приложения) поради своята асинхронна природа.

Така че можете да направите точки 2. и 1. с помощта на Омаха. Страхувам се, че не знам как бихте направили 3.

person Declan Nelson    schedule 27.10.2020

Само някои мисли, които имах.

1 изглежда проблематично, защото в крайна сметка се справяте със ситуацията, която се опитвате да разрешите, защото в даден момент програмата за актуализиране ще се нуждае от актуализиране. 3 звучи добре, но ако под „разменен“ имате предвид използването на някакво фантастично отражение за зареждане на dll по време на изпълнение, не съм сигурен дали производителността ще стане проблем.

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

person Spencer Ruport    schedule 22.10.2009
comment
+1 Всъщност имаме самообновяваща се услуга .Net Windows и тя прави това, когато изтегля по-нова версия: 1) Инсталира нова услуга, ако двоичните версии се различават (може да е просто промяна в конфигурацията, в който случай просто искаме за рестартиране). 2) Създайте помощен процес, който: A) Спира стара услуга, B) Стартира нова услуга, C) (ако са версии, а не само конфигурационни файлове) Премахнете старата услуга. Това беше една от най-трудните области за коригиране и много грешки бяха регистрирани срещу това, а отстраняването на грешки беше кучка :( - person Hamish Grubijan; 03.08.2010
comment
Първо, ако новата услуга е изградена срещу по-нова .net рамка ... о, момче, о, момче, о, момче! Ние използваме някои .bat файлове, някак работи (с рестартиране понякога), но е гадно. Второ, тъй като отстраняването на грешки е мъка, LOG, LOG, LOG! Помощният процес не трябва да пише в същия журнал, така че трябва да пише в своя собствен. Trace.Writeln е най-лесният начин за влизане, като се има предвид, че има правилен запис във файл app.config. Само не забравяйте да настроите автоматичното промиване на true. Нещо толкова крехко е по-добре да работи бавно, отколкото без намеци. Говорейки за бавно, помощникът така или иначе трябва да заспи няколко секунди. - person Hamish Grubijan; 03.08.2010
comment
@Dmitri Nesteruk, първо тук е xml за регистриране: ‹?xml версия=1.0?› ‹configuration› ‹system.diagnostics› ‹trace autoflush=true indentsize=4› ‹listeners› ‹remove name=Default /› ‹add name =myListener type=System.Diagnostics.TextWriterTraceListener initializeData=c:\myListener.log/› ‹/listeners› ‹/trace› ‹/system.diagnostics› ‹startup›‹supportedRuntime version=v4.0 sku=.NETFramework,Version= v4.0/›‹/startup›‹/configuration› и влизате с Trace.Writeline и т.н. - person Hamish Grubijan; 06.05.2011
comment
Тази връзка е полезна: csharp-examples.net/install-net-service Такъв е и този: stackoverflow.com/questions/358700/ И този: codeproject.com/Answers/188726/ И това: dotnetmonster.com/Uwe/Forum.aspx/dotnet-csharp/2987/ И това: social.msdn.microsoft.com/Forums/en -IE/csharplanguage/нишка/ - person Hamish Grubijan; 06.05.2011
comment
Ето как извиквате актуализиращия инструмент: string strNewVersion = Path.Combine(_application.Client.BaseDir, _server.AvailableVersion + \\service.exe); var inst = new AssemblyInstaller(strNewVersion, нов низ[] { }); installer.Installers.Add(inst); installer.Install(нова System.Collections.Hashtable()); var psii = нов ProcessStartInfo(); psii.Arguments = String.Format({0} {1}, GetCurrentRunningDirVersion(), _server.AvailableVersion); psii.Име на файл = UpdaterHelper.exe; psii.UseShellExecute = невярно; var procc = Process.Start(psii); procc.WaitForExit(); // Добавяне на сън преди и или след може би. - person Hamish Grubijan; 06.05.2011

Използвам опция 1. Процесът на актуализиране се актуализира много рядко в наши дни. Той използва XML файл, съдържащ подробности за това откъде да вземете файловете (в момента поддържа SVN, работи върху добавянето на поддръжка на NuGet) и къде да ги поставите. Той също така посочва кои са услуги и кои са уебсайтове и посочва името на услугата, която да се използва за всеки проект.

Процесът анкетира източника, ако има налична нова версия, той я копира в директория с номера на нова версия и след това актуализира услугата. Той също така съхранява 5 копия на всяка актуализация, което улеснява връщането назад, ако има проблем.

Ето основната част от кода за програмата за актуализиране, която спира съществуващата услуга, копира файловете и след това я рестартира.

if (isService)
{
    log.Debug("Stopping service " + project.ServiceName);

    var service = GetService(project);
    if (service != null && 
        service.Status != System.ServiceProcess.ServiceControllerStatus.Stopped && service.Status != System.ServiceProcess.ServiceControllerStatus.StopPending)
    {
        service.Stop();
    }

    service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped, new TimeSpan(0, 1, 0));
    if (service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
        log.Debug("Service stopped");
    else
        log.Error("ERROR: Expected Stopped by Service is " + service.Status);

}

log.Debug("Copying files over");
CopyFolder(checkoutDirectory, destinationDirectory);

if (isService)
{
    log.Debug("Starting service");
    var service = GetService(project);

    // Currently it doesn't create services, you need to do that manually
    if (service != null)
    {
        service.Start();

        service.WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running, new TimeSpan(0, 1, 0));

        if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
            log.Debug("Service running");
        else
            log.Error("Service " + service.Status);
    }
}
person Ian Mercer    schedule 17.09.2011