Wix: Windows Service af og til afinstalleres, når du opgraderer

Indlæg af Hanne Mølgaard Plasc

Problem



Vi installerer vores software med Wix. Vores opsætning installerer også en Windows-tjeneste. For at give brugerne mulighed for at ændre loginoplysningerne til Windows-tjenesten, vil vi kun installere tjenesten ved første installation og kun slette den ved afinstallation. For opgraderinger stopper vi manuelt tjenesten, så filerne kan opgraderes.


Vi har det her, men for nylig fandt vi, at Windows-tjenesten på nogle maskiner bliver afinstalleret under UnpublishFeatures:


Dette hvis fra en mislykket opgraderingslog:


Action 13:41:38: UnpublishFeatures. Unpublishing Product Features
MSI (s) (D8:EC) [13:41:38:346]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (D8:EC) [13:41:38:346]: Note: 1: 1402 2: UNKNOWNInstallerFeatures84B659030632F794E93A7CB19A87DB8E 3: 2 
MSI (s) (D8:EC) [13:41:38:346]: Executing op: ActionStart(Name=StopServices,Description=Stopping services,Template=Service: [1])
Action 13:41:38: StopServices. Stopping services
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:362]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=2,Wait=1,)
StopServices: Service: Ridder iQ Web API
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ActionStart(Name=DeleteServices,Description=Deleting services,Template=Service: [1])
Action 13:41:38: DeleteServices. Deleting services
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (D8:EC) [13:41:38:393]: Executing op: ServiceControl(,Name=RidderIQWebApi,Action=8,Wait=1,)
DeleteServices: Service: Ridder iQ Web API


Dette hvis fra en log fra en succesfuld opgradering:


Action 11:53:24: UnpublishFeatures. Unpublishing Product Features
MSI (s) (CC:3C) [11:53:24:976]: Executing op: FeatureUnpublish(Feature=Main,,Absent=2,Component=
UnpublishFeatures: Feature: Main
MSI (s) (CC:3C) [11:53:24:977]: Note: 1: 1402 2: UNKNOWNInstallerFeatures84B659030632F794E93A7CB19A87DB8E 3: 2 
MSI (s) (CC:3C) [11:53:24:978]: Executing op: ActionStart(Name=RemoveFiles,Description=Removing files,Template=File: [1], Directory: [9])
Action 11:53:24: RemoveFiles. Removing files


Som du kan se Windows Installer hopper over StopServices/DeleteServices-handlingerne og begynder at fjerne filerne. Da tjenesten er slettet på UnpublishFeatures senere under opsætningen, forsøger den at konfigurere tjenesten, men fejler, fordi den ikke længere er installeret:


MSI (s) (D8:68) [13:42:34:772]: Executing op: CustomActionSchedule(Action=ExecServiceConfig,ActionType=3073,Source=BinaryData,Target=ExecServiceConfig,CustomActionData=)
MSI (s) (D8:90) [13:42:34:772]: Invoking remote custom action. DLL: C:WindowsInstallerMSI170B.tmp, Entrypoint: ExecServiceConfig
ExecServiceConfig:  Error 0x80070424: Service 'RidderIQWebApi' does not exist on this system.
ExecServiceConfig:  Error 0x80070424: Failed to get service: RidderIQWebApi
CustomAction ExecServiceConfig returned actual error code 1603 (note this may not be 100\% accurate if translation happened inside sandbox)
Action ended 13:42:35: InstallFinalize. Return value 3.


Mit gæt er, at dette sker, fordi handlingen til komponenten er forskellig for begge opgraderinger. For den mislykkede opgradering er disse komponenthandlingerne:


MSI (s) (D8:68) [13:41:26:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (D8:EC) [13:41:36:400]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local;   Request: Absent;   Action: Absent


For den succesfulde opgradering er disse komponenthandlingerne:


MSI (s) (CC:44) [11:53:17:386]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Absent;   Request: Local;   Action: Local
MSI (s) (CC:3C) [11:53:22:850]: Component: cmp.SR.SDKWebAPI.Service.exe; Installed: Local;   Request: Absent;   Action: FileAbsent


Som du kan se, er handlingen til den mislykkede opgradering fraværende, og for den succesfulde opgradering er FileAbsent. Fra hvad jeg har læst FileAbsent betyder, at funktionen geninstalleres og Fraværende betyder at funktionen fjernes.


Mit spørgsmål er, hvordan er aktionerne for komponenter bestemt, og hvorfor er det på en maskine fraværende og på en anden maskine FileAbsent. Og er der en måde at løse dette på?


Komponenten hvis konfigureret som denne:


  <Component Id="cmp.SR.SDKWebAPI.Service.exe" Guid="">
    <File Id="fil.SDKWebAPI.Service.exe" Source="SDKWebAPI.Service.exe" KeyPath="yes" />
    <File Id="fil.SDKWebAPI.Service.exe.config" Source="SDKWebAPI.Service.exe.config" KeyPath="no" />
    <ServiceInstall Id="SDKWebAPI.Service.exe.Installer"
                    Type="ownProcess"
                    Name="RidderIQWebApi"
                    DisplayName="Ridder iQ Web API"
                    Description="Ridder iQ Web API service"
                    Start="auto"
                    Account="LocalSystem"
                    ErrorControl="ignore">
      <util:ServiceConfig FirstFailureActionType="restart" 
                          SecondFailureActionType="restart"
                          ThirdFailureActionType="restart"
                          RestartServiceDelayInSeconds="60" 
                          ResetPeriodInDays="0" />
    </ServiceInstall>
  </Component>

Bedste reference


Blank komponent GUID : Guid="" er det noget du satte for nylig? Dette vil efter min opfattelse sætte en tom GUID for komponenten, hvilket betyder at den bliver installeret ved første installation og aldrig rørt eller opgraderet bagefter (medmindre du har fundet noget trick til at geninstallere komponenten under opgradering) - og det vil ikke være afinstalleret enten så vidt jeg husker.


Sen REP : Ovenstående (blank GUID) ser ikke ud til, hvad du har til hensigt. Du vil bare have komponenten ikke afinstalleret ved større opgradering, i hvilket tilfælde hvad du generelt ville gøre, ville være at flytte RemoveExistingProducts sent i InstallExecuteSequence - noget som kræver, at du følger alle komponentregler til brevet . Dette er meget kompliceret runtime adfærd, men et simpelt koncept. I det væsentlige vil din nye version installeres som en patch - overskrive filer uden først at afinstallere dem - hvilket gør det muligt at bevare dine serviceoplysninger, da komponenten hosting tjenesten aldrig afinstalleres.


Tidlig REP : Bare for posten er den fælles måde at gøre store opgraderinger på at planlægge RemoveExistingProducts tidligt i InstallExecuteSequence, hvilket betyder at alle filer er afinstalleret, og derefter geninstalleret. Denne fremgangsmåde bruges, fordi den tillader sløv komponentreferencer. Det er velkendt at udslette brugerdata som licensnøgler, serviceoplysninger, osv. ...


Permanent komponent : En anden tilgang ville være at indstille hosting-komponenten til at være permanent. Derefter vil den aldrig blive afinstalleret under en større opgradering (selvom du bruger tidligt REP), men ikke under en regelmæssig afinstallation, og derfor strækker du den pågældende fil (er) på systemet (medmindre du tilføjer dine egne brugerdefinerede oprydningsfunktioner - hvilket kan være meget fejlberettiget).


Custom Backup Mechanism : Andre er afhængige af deres egne brugerdefinerede handlinger (eksempel) for at sikkerhedskopiere de data, der bliver slettet under opgraderingen, og derefter genanvende dem efter opgraderingen er afsluttet. En meget fejltagende tilgang i min opfattelse .


Kun MSI-service : Du kan også sætte serviceinstallationen i sin egen MSI for at gøre opdateringen mere kontrollerbar for dig - eller hvis hovedinstallationen ikke kan gøres til Overhold komponentreglerne. Dette er også noget kompliceret, men bedre end tilpassede handlinger efter min mening.


Mindre opgradering : Hvis du kan bruge mindre opgraderinger til at installere opgraderinger, kan du undgå dette service-legitimationsproblem. Jeg vil bare linke til et andet svar, der beskriver dette: Genstart Windows-service under WIX-opgradering.


(Managed) servicekonti : Du kan bruge en almindelig servicekonto uden (om servicekonti) legitimationsoplysninger til at køre tjenesten - som f.eks. LocalService, LocalSystem eller NetworkService (hvilket naturligvis er ikke muligt for dig vil jeg antage). Eller de nyere begreber af administrerede servicekonti, gruppeadministrerede servicekonti eller virtuelle konti trin for trin info (begreber jeg ikke ved nok om). [15] [16] [17] [18] [19] [20]


Andre tilgange : Der er ingen tvivl om andre tilgange også. Jeg formoder, at du kunne holde servicekonfigurationen ud af MSI og anvende den via et script. Jeg vil ikke anbefale det. Jeg ved, at nogle mennesker skifter mellem at bruge tjenester og planlagte opgaver afhængigt af arten af ​​den aktuelle opgave (i det væsentlige skifte til planlagte opgaver, hvis det er en opgave, der kun kører en gang imellem.) Selvom det er risikabelt, antager jeg, at du kunne udskyde servicekonfigurationen til en forhøjet EXE, som brugeren starter efter installationen (brugeren skal være administrator i dette tilfælde selvfølgelig), som så kan oprette konfigureringen med en vis interaktivitet (fejl og statusmeddelelser direkte til brugeren - og ikke bare skjult i logfiler), som nogle gange kan hjælpe med at få folk til at gå. Ikke min anbefalede tilgang selv - forhøjede handlinger er, hvad der er et opsætningsforslag. konfiguration jeg kan lide at gøre i applikationen. [21]





Almindelige MSI-problemer i real-verden : Jeg skrev om nogle af de fælles problemer, der ses i praktisk anvendelse af MSI en tid tilbage, og her er det: Hvordan undgår jeg fælles design fejl i min WiX/MSI implementeringsløsning? Det er ikke fantastisk. Jeg er ikke særlig glad for det - det mangler på flere måder end en - men der er det, hvis det kan hjælpe. Det var den bedste indsats i den ledige tid. Tag venligst det til hvad det er: en ufærdig dump af virkelige problemer med et par punkter her og der for hvad du kan forsøge at håndtere problemet.