Jak zatrzymać i usunąć pliki usługi windows?

0

Witam. To ostatni błąd z jakim spotkałem się w moim aktualizatorze:
Nie jestem w stanie usunąć plików usługi po jej zatrzymaniu i usunięciu:

// Zatrzymywanie i usuwanie usługi
                ServiceController RunService = ServiceController.GetServices().FirstOrDefault(x => x.ServiceName == AppIdentification.RunServiceName);
                if(RunService != null)
                { 
                    try
                    {
                        if(RunService.Status != ServiceControllerStatus.Stopped)
                        {
                            RunService.Stop();
                            RunService.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 30));
                            RunService.Close();
                        }
                        
                        ManagedInstallerClass.InstallHelper(new string[] { "/u", System.AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + AppIdentification.RunServiceName + ".exe" });
                    }
                    catch(Exception e)
                    {
                        Help.AddLog(">>> UpdateProcedure nie udało się zatrzymać usługi " + AppIdentification.RunServiceName, e.Message);
                        return false;
                    }
                }

Podczas usuwania folderu gdzie są pliki z usługą:

// Usuwanie plików z folderu RunService
                bool DeleteRunServiceFileSuccess = false;
                try
                {
                    if (Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder))
                        Directory.Delete(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder, true);
                    Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder);
                    DeleteRunServiceFileSuccess = true;
                }
                catch (Exception e)
                {
                    Help.AddLog("UpdateProcedure nie udało się usunąć starych plików", e.Message);
                }
                if (!DeleteRunServiceFileSuccess)
                {
                    GSDb.DbOperation.Export(DbConfig, "UPDATE `AppIdentification` SET `IsUpdatingNow`=0 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                    return false;
                }

otrzymuję wyjątek o odmowie dostępu do pliku. Czy moje usuwanie usługi działa nieprawidłowo? jeżeli chodzi o menadżer zadań w zakładce usługi usługa znika, więc chyba jest odinstalowana?

Z logów otrzymuję coś takiego:
(pierwsza aktualizacja, kiedy pierwszy raz kopiuje pliki jest ok, druga rzuca wyjątek przy próbie usunięcia starych plików)

1846 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.3 do 1.0.5
1848 - UpdateProcedure zakończyło aktualizację do wersji 1.0.5
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1852 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1845 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1846 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)

0

Nie wiem czy używasz TopShelf.
Ja w jakimś starszym projekcie z TopShelf mam w instalatorze InnoSetup coś takiego. Chyba działało, ale teraz nie sprawdzałem.

[Run]
Filename: "{app}\exec_serwisu.exe"; Parameters: "uninstall"
Filename: "{app}\exec_serwisu.exe"; Parameters: "install start"

[UninstallRun]
Filename: "{app}\exec_serwisu.exe"; Parameters: "stop"
Filename: "{app}\exec_serwisu.exe"; Parameters: "uninstall"

[Code]

function PrepareToInstall(var NeedsRestart: Boolean): String;
var
  ChecksumBefore, ChecksumAfter: String;
  ResultCode: Integer;
  begin

    if FileExists(ExpandConstant('{app}\exec_serwisu.exe'))
    then
      Exec(ExpandConstant('{app}\exec_serwisu.exe'), 'stop', ExpandConstant('{app}'), SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode)

end;
0

Uninstall mi działa. teraz wewnątrz tej usługi która się zainstalowała jest aktualizacja drugiej usługi. jest ona pobierana z serwera FTP, instalowana i uruchamiana. To działa. Przy drugiej aktualizacji trzeba usunąć poprzednią, czyli usunąć pliki usługi nr 2, zastąpić je nowymi pobranymi z serwera i uruchomić usługę. Ale jak wspomniałem, powyższy kod rzuca wyjątek i nie mogę się z nim uporać. Ręczne usunięcie też nie działa, dostaję informację, że plik jest otwarty w innym programie.

Po zainstalowaniu z instalatora:
screenshot-20200415194523.png

Po pierwszej aktualizacji:
screenshot-20200415194542.png
screenshot-20200415194604.png
screenshot-20200415194637.png

Po drugiej aktualizacji:
screenshot-20200415194821.png
screenshot-20200415194848.png

1907 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.5 do 1.0.6
1909 - UpdateProcedure zakończyło aktualizację do wersji 1.0.6
1906 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.6 do 1.0.7
1913 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)
1906 - UpdateProcedure rozpoczyna aktualizację z wersji 1.0.6 do 1.0.7
1907 - UpdateProcedure nie udało się usunąć starych plikówPrinterInformationRunSvc (Odmowa dostępu do ścieżki „PrinterInformationRunSvc.exe”.)

Nie mogę podmienić exeka w nowszej wersji bo nie mogę go usunąć (tą drugą usługę pobraną przez aktualizator)
screenshot-20200415195127.png

Pokazuje mi, że plik PrinterInformationRunSvc (usługa2) jest otwarta w moim aktualizatorze...

EDIT:
Jeżeli dałem Wam za mało informacji / kodu powiedzcie.

0

A ta druga usługa nie może mieć swojego instalatora, który zrobi to samo i będzie uruchamiany przez pierwszy instalator?

0

Pierwszy instalator instaluje Service1. I ten Service1 ma za zadanie kontrolować wersję i decydować, czy Service może działać czy nie oraz pilnować najnowszej wersji Service2
Service1 ściąga pliki Service2 z serwera FTP, usuwa service2, zastępuje pliki i uruchamia service2. tak to musi działać. Tylko w którym miejscu w kodzie może być coś nie tak.

ManagedInstallerClass.InstallHelper(new string[] { "/u", System.AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + AppIdentification.RunServiceName + ".exe" });

Może tutaj niepoprawnie odinstalowuję usługę?

A da się z poziomu c# wykonać skrypt PowerShella? Nie mogę znaleźć w NuGet System.Management.Automation.dll

1

Serwis 1 (s1) ściąga serwis 2 (s2) w postaci instalatora i go uruchamia. Instalator s2 robi sam co trzeba i już.
Z TopShelf dostajesz proste parametry do zarządzania. Używasz TopShelf?

0

Nie używam. Dopiero teraz przeczytałem co to jest. Czyli wraz z plikami dll i exe mam pobrać "instalator", który zainstaluje mi usługę? Spróbuję to zmienić, jednak nadal chciałbym się dowiedzieć, co jest nie tak w moim kodzie

0

Ja bym zrobił instalator w InnoSetup dla s2 i go używał.
Twojeg kodu nie wyjaśnię bo nigdy czegoś takiego nie pisałem.

0

Tylko zależy mi na automatyzacji, aby użytkownik nie musiał klikać dalej -> dalej -> instaluj itp. chciałbym, aby aktualizacja przebiegała w "tle" bez dodatkowych plików.

0

Da się zrobić bez problemów cichy instalator w InnoSetup.

0

Dobra wygrałeś, jeżeli go zrobię a biorę się za to za chwilę to jest szansa uruchomić go z kodu i sprawdzić poprawność wykonania instalacji?

1

Instalator to zwykły exe więc da się to uruchomić. Ja mam w app winforms tak, że sama aplikacja sprawdza wersję, ściąga instalator i uruchamia instalator z aktualizacją tylko musi się szybko sama zamknąć bo aktualizuje siebie :).

0

Uruchamiam instalator i deinstalator z poziomu cmd i wszystko działa ! <3 Jesteście wielcy!!!!!!! Co prawda zajęło mi to ponad 24h ale było warto haha

Tutaj cały kod aktualizacji z kontrolą wersji, może komuś się przyda

/// <summary>
        /// Przeprowadza procedurę aktualizacji, jeżeli jest to wymagane. Zwraca true, jeżeli dozwolone jest uruchomienie najnowszej wersji aplikacji
        /// </summary>
        /// <param name="DbConfig">Konfiguracja połączenia z bazą danych</param>
        /// <param name="flags">Aktualne ustawienia Updatera</param>
        /// <returns></returns>
        public static bool UpdateProcedure(GSDb.DbConfig DbConfig, Flags flags)
        {
            Task<bool> UpdateRequiredTask = Task<bool>.Factory.StartNew(() =>
            {
                // sprawdzanie, czy wymagana aktualizacja
                ServerSettings ServerSettings = ServerSettings.GetSettings(DbConfig);        
                if (!ServerSettings.Success)
                {
                    Help.AddLog(">>> Błąd podczas inicjowania procedury aktualziacji", ServerSettings.Exception.Message);
                    return false;
                }  
                bool RequireUpdate = Help.NewerVersionAvailable(flags.AppData.AppVersion, ServerSettings.LastestVersion);
                if (!RequireUpdate)
                    return true;
                
                // sprawdzanie, czy możliwa aktualizacja
                if(ServerSettings.IsUpdating)
                    return false;

                Help.AddLog(">>> Rozpoczynanie aktualizacji z wersji " + flags.AppData.AppVersion + " do " + ServerSettings.LastestVersion);

                // Oznaczenie Aplikacji jako aktualizującej się
                GSDb.DbResult SetAsUpdatingResult = GSDb.DbOperation.Export(DbConfig,
                    "UPDATE `AppIdentification` SET `IsUpdatingNow`=1 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                if(!SetAsUpdatingResult.Success)
                {
                    Help.AddLog(">>> Aktualizacja nie powiodła się", SetAsUpdatingResult.Exception.Message);
                    return false;
                }

                // Pobieranie plików z serwera FTP i zapisanie ich do Folderu Run 
                bool DownloadFilesSuccess = false;
                try
                {
                    if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder))
                        Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder);

                    GSUpdater.Net.FTPUpdater updater = new GSUpdater.Net.FTPUpdater(flags.FtpConfig);
                    IEnumerable<string> FTPFiles = updater.ListFiles(null);
                    foreach (string f in FTPFiles)
                    {
                        FileInfo fInfo = new FileInfo(f);
                        Help.AddLog(">>> Pobieranie " + fInfo.Name);
                        updater.DownloadFile(f, AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + fInfo.Name);
                    }
                    DownloadFilesSuccess = true;
                }
                catch(Exception e)
                {
                    Help.AddLog(">>> Błąd podczas pobierania najnowszych plików", e.Message);
                }
                if(!DownloadFilesSuccess)
                {
                    GSDb.DbOperation.Export(DbConfig, "UPDATE `AppIdentification` SET `IsUpdatingNow`=0 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                    return false;
                }

                // Zatrzymywanie i usuwanie usługi
                if (true)
                {
                    try
                    {
                        if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"unins000.exe"))
                        {
                            Help.AddLog(">>> Odinstalowywanie usługi " + AppIdentification.RunServiceName);
                            System.Diagnostics.Process process = new System.Diagnostics.Process();
                            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                            startInfo.FileName = "\"" + AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"unins000.exe" + "\"";
                            startInfo.Arguments = "/verysilent";
                            process.StartInfo = startInfo;
                            process.Start();
                            process.WaitForExit();
                        }
                    }
                    catch (Exception e)
                    {
                        Help.AddLog(">>> Błąd deinstalacji usługi " + AppIdentification.RunServiceName, e.Message);
                        GSDb.DbOperation.Export(DbConfig, "UPDATE `AppIdentification` SET `IsUpdatingNow`=0 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                        return false;
                    }
                }

                // Uruchomienie instalatora usługi
                if (true)
                {
                    try
                    {
                        if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"PrinterInformationRunSetup.exe"))
                        {
                            Help.AddLog(">>> Instalowanie zaktualizowanej usługi " + AppIdentification.RunServiceName);
                            System.Diagnostics.Process process = new System.Diagnostics.Process();
                            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                            startInfo.FileName = "\"" + AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"PrinterInformationRunSetup.exe" + "\"";
                            startInfo.Arguments = "/verysilent";
                            process.StartInfo = startInfo;
                            process.Start();
                            process.WaitForExit();
                        }
                        else
                            throw new Exception("Nie znaleziono pliku " + "\"" + AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"PrinterInformationRunSetup.exe" + "\"");
                    }
                    catch (Exception e)
                    {

                        Help.AddLog(">>> Nie udało się zainstalować usługi " + AppIdentification.RunServiceName, e.Message);
                        GSDb.DbOperation.Export(DbConfig, "UPDATE `AppIdentification` SET `IsUpdatingNow`=0 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                        return false;
                    }
                }

                // Usunięcie instalatora
                if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"PrinterInformationRunSetup.exe"))
                    File.Delete(AppDomain.CurrentDomain.BaseDirectory + AppIdentification.RunServiceFolder + @"PrinterInformationRunSetup.exe");

                // Aktualizowanie wersji w bazie danych
                GSDb.DbResult UpdateDbVersion = GSDb.DbOperation.Export(DbConfig,
                    "UPDATE `AppIdentification` SET `AppVersion`=" + CreateSqlText(ServerSettings.LastestVersion) +  " WHERE `ID`=" + flags.AppData.AppIdentificationID);
                
                // Oznaczenie Aplikacji jako nieaktualizującej się
                GSDb.DbResult SetAsNotUpdatingResult = GSDb.DbOperation.Export(DbConfig,
                    "UPDATE `AppIdentification` SET `IsUpdatingNow`=0 WHERE `ID`=" + flags.AppData.AppIdentificationID);
                if (!SetAsNotUpdatingResult.Success)
                {
                    Help.AddLog(">>> Nie udało sie potwierdzić zakończenia aktualizacji", SetAsNotUpdatingResult.Exception.Message);
                    return false;
                }

                flags.AppData.AppVersion = ServerSettings.LastestVersion;
                Help.AddLog("UpdateProcedure zakończyło aktualizację do wersji " + ServerSettings.LastestVersion);
                return true;
            });
            return UpdateRequiredTask.Result;
        }

Tutaj plik instalatora który instaluje UpdateService
https://pastebin.com/x7202Kq1
Tutaj plik instalatora który instaluje RuNService (tego instalatora uruchamia UpdateService)
https://pastebin.com/BEJjWKz0

naprawde dziękuję, że nie musiałem sam przez to wszystko przechodzić i dostałem naprawdę cenne wskazówki :)

1

Dobrze, że się udało. Gdybyś kiedyś to refactorował w przyszłości to ja bym wydzielił kod sprawdzający wersję od ściągania nowej wersji i samej aktualizacji (uruchomienie instalatora).

0

Teraz jak już działa zajmę się zabiegami kosmetycznymi, a te if(True) jest tylko po to żebym zwinął te klamry 😁 to będą oddzielne metody.

1 użytkowników online, w tym zalogowanych: 0, gości: 1