2010-08-08 23 views
13

Mam usługa Windows, zbudowany przy użyciu C#, który jest instalowany za pośrednictwem projektu instalacji VS2008, i mam kilka problemów występujących w procesie deinstalacji:Prawidłowy sposób odinstalowania usługi Windows?

Usługa nie jest zatrzymany przed deinstalacją

Po uruchomieniu procedury deinstalacji generuje błąd dotyczący używanych plików. Kliknięcie przycisku Kontynuuj poprawnie instaluje instalator, ale usługa nadal pojawia się na liście, więc nie jest poprawnie odinstalowywana.

(Obecnie muszę uciekać się do usunięcia go ręcznie przy użyciu sc delete servicename).

Próbuję zatrzymać usługę przed deinstalacją za pomocą następującego kodu, ale nie wydaje się być przy Efekt:

protected override void OnBeforeUninstall(IDictionary savedState) 
{ 
    base.OnBeforeUninstall(savedState); 
    ServiceController serviceController = new ServiceController(MyInstaller.ServiceName); 
    serviceController.Stop(); 
} 

Gdy ten kod nazywa i jak mogę zatrzymać usługę przed odinstalowaniem?

Folder instalacyjny nie usunięte po odinstalowaniu

Aplikacja tworzy także niektóre pliki w to folder instalacyjny po uruchomieniu. Po odinstalowaniu folder instalacyjny (C: \ Program Files \ MyApp) nie jest usuwany i zawiera pliki utworzone przez aplikację, ale wszystkie inne pliki, które zostały faktycznie zainstalowane przez instalatora, zostały pomyślnie usunięte.

Czy proces odinstalowywania może usunąć folder instalacji, w tym wszystkie wygenerowane pliki w tym folderze, a jeśli tak, to w jaki sposób?

Dzięki.

Odpowiedz

6

Z korzyścią dla każdego, kto szuka odpowiedzi na te problemy:

Usługa nie jest zatrzymany przed deinstalacją

jeszcze nie znaleźli rozwiązanie tego.

Folder instalacyjny nie usunięte po odinstalowaniu

Sposób OnAfterUninstall w instalatorze projekt musi zostać zastąpione, a wszelkie powstałe pliki muszą zostać usunięte. Folder instalatora aplikacji jest automatycznie usuwany, jeśli po tym kroku nie zawiera żadnych plików.

protected override void OnAfterUninstall(IDictionary savedState) 
{ 
    base.OnAfterUninstall(savedState); 

    string targetDir = Context.Parameters["TargetDir"]; // Must be passed in as a parameter 

    if (targetDir.EndsWith("|")) 
     targetDir = targetDir.Substring(0, targetDir.Length-1); 

    if (!targetDir.EndsWith("\\")) 
     targetDir += "\\"; 

    if (!Directory.Exists(targetDir)) 
    { 
     Debug.WriteLine("Target dir does not exist: " + targetDir); 
     return; 
    } 

    string[] files = new[] { "File1.txt", "File2.tmp", "File3.doc" }; 
    string[] dirs = new[] { "Logs", "Temp" }; 

    foreach (string f in files) 
    { 
     string path = Path.Combine(targetDir, f); 

     if (File.Exists(path)) 
      File.Delete(path); 
    } 

    foreach (string d in dirs) 
    { 
     string path = Path.Combine(targetDir, d); 

     if (Directory.Exists(d)) 
      Directory.Delete(d, true); 
    } 

    // At this point, all generated files and directories must be deleted. 
    // The installation folder will be removed automatically. 
} 

Pamiętaj, folder instalacyjny musi być przekazany jako parametr:

  • prawym przyciskiem myszy na projekcie instalacji, a następnie wybierz Widok -> Akcje niestandardowe
  • Niestandardowe działania będą otwarte w główne okno. Kliknij prawym przyciskiem myszy "Wyjście pierwotne z XXX" w węźle Odinstaluj i wybierz "Okno właściwości"
  • W oknie właściwości, w obszarze CustomActionData, wprowadź: /TargetDir = "[TARGETDIR] |" (uwaga na końcu rury, nie usuwaj tego).

Spowoduje to przekazanie folderu instalacji jako parametru do procedury odinstalowywania, dzięki czemu wiadomo, gdzie zainstalowano aplikację i można usunąć wygenerowane pliki i foldery.

+1

Chciałbym osobiście odpowiedzieć na twój pierwszy numer. Opublikuj go, jeśli kiedykolwiek to zrozumiesz. – PaulH

+0

@Mun Dodałem [ten kod] (http://www.primordialcode.com/blog/post/msi-simple-delete-files-custom-action) do metody 'OnAfterUninstall', ale jest napisane, że plik jest używany przez inny proces lub odmowa dostępu –

1

Najprawdopodobniej zamknięcie usługi zajmuje tylko trochę czasu, a użytkownik kontynuuje pracę, zanim usługa całkowicie się zatrzyma. Spróbuj wywołać metodę WaitForStatus(ServiceControllerStatus).

Spowoduje to, że twój kod zaczeka, aż usługa przetworzy komunikat "stop" i wyłączy się. Gdy usługa zostanie faktycznie zamknięta, nie będzie dłużej trzymała się żadnych uchwytów plików.

+1

Próbowałem tego bez żadnego szczęścia. Niektóre dalsze debugowanie ujawnia, że ​​żadna z metod deinstalacji (OnBeforeUninstall, OnAfterUninstall, Uninstall) nie jest wywoływana zanim system Windows wyświetli ostrzeżenie "Pliki w użyciu", dlatego usługa nie jest zatrzymywana. – Mun

+0

Ah, ok. Inne pytanie, kiedy mówisz "pliki utworzone przez aplikację", masz na myśli pliki nieobecne, gdy instalator ukończy instalację, raczej utworzone podczas uruchamiania aplikacji? Pliki te mogą wymagać ręcznego czyszczenia (onafterinstall?) ... wielu instalatorów będzie bardzo ostrożnych w kwestii "automatycznego" usuwania. –

+1

Tak, udało mi się rozwiązać ten problem, przekazując katalog instalacyjny jako parametr niestandardowy i zastępując metodę OnAfterUninstall, aby usunąć pliki utworzone przez aplikację. Jeśli folder będzie pusty po tym, instalator automatycznie go usunie. – Mun

Powiązane problemy