Błąd "MSI 2769" jest dość często spotykanym błędęm, występującym podczas instalacji, reperacji lub deinstalacji pakietów wykonanych w "Microsoft Visual Studio" i bazujących na technologii ".Net Framework". Elementami powodującymi powstawanie tego błędu są najczęściej błędnie napisane klasy lub akcje ("Custom actions").

W poniższym opisie posłużono się pakietem opartym na klasie "ProjectInstaller" oraz jej komponentach "ServiceProcessInstaller" i "ServiceInstaller".

Instalacja oraz deinstalacjia pakietu przebiega bezproblemowo jednak podczas reperacji generowany jest "błąd 1001", informujący o tym, że serwis jest już zainstalowany w systemie i nie wymaga ponownej instalacji.

Błąd 1001 (MSI 2769)

Rys.1. Błąd reperacji pakietu

"Błąd 1001" ma swoje odzwierciedlenie w tabeli "Error" bazy danych pakietu-msi.

Tabela "Error" w edytorze Orca

Rys.2. Tabela "Error" w edytorze ORCA

Błędy o numeracji od 1000 do 1999 są błedami wewnętrznymi Windows Installera i są obsługiwane przez wpisy w tabeli "Errors", natomiast o numeracji od 2500 do 3000 są błędami wywołania akcji ("Custom actions") i bardzo często mają krytyczny wpływ na instalację pakietu.

Wpis w tabeli "Errors" nie mówi nam za wiele i aby znaleźć prawdziwe źródło odpowiedzialne za powstały błąd, należy zajrzeć do logu instalacyjnego (szukamy więc informacji o błędzie 1001). 

MSI (s) (80:FC) [14:14:45:888]: Generating random cookie.

MSI (s) (80:FC) [14:14:45:904]: Created Custom Action Server with PID 1288 (0x508).

MSI (s) (80:F0) [14:14:45:966]: Running as a service.

MSI (s) (80:04) [14:14:45:966]: Hello, I'm your 32bit Elevated custom action server.

MSI (s) (80:F4) [14:15:55:524]: Leaked MSIHANDLE (9) of type 790531 for thread 1660

MSI (s) (80:F4) [14:15:55:524]: Note: 1: 2769 2: _09A1EA63_58DC_4827_BFA4_44059F3467B0.install 3: 1 

MSI (c) (B4:C8) [14:14:46:435]: Font created.  Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg Fehler 1001. Error 1001. Der angegebene Dienst ist bereits vorhanden

DEBUG: Error 2769:  Custom Action _09A1EA63_58DC_4827_BFA4_44059F3467B0.installdid not close 1 MSIHANDLEs.

Bei der Installation dieses Pakets ist ein unerwarteter Fehler aufgetreten. Es liegt eventuell ein das Paket betreffendes Problem vor. Der Fehlercode ist 2769. Argumente: _09A1EA63_58DC_4827_BFA4_44059F3467B0.install, 1, 

MSI (s) (80:98) [14:15:55:524]: User policy value 'DisableRollback' is 0

MSI (s) (80:98) [14:15:55:524]: Machine policy value 'DisableRollback' is 0

Aktion beendet um 14:15:55: InstallExecute. Rückgabewert 3.

Jak można zauważyć podczas reperacji produktu w logu instalacyjnym zapisywany jest błąd o numerze "2769", którego źródłem jest akcja  "_09A1EA63_58DC_4827_BFA4_44059F3467B0.install"

DEBUG: Error 2769:  Custom Action _09A1EA63_58DC_4827_BFA4_44059F3467B0.installdid not close 1 MSIHANDLEs.

Aby stwierdzić czy serwis jest instalowany w standardowy sposób czy przy pomocy akcji ("Custom actions") przechodzimy do tabel "ServiceInstall" i "ServiceControl" i sprawdzamy ich zawartość. Obie tabele są puste, co oznacza, że serwis jest instalowany przy pomocy akcji. W tabeli "CustomActions" znajdziemy wszystkie akcje odpowiedzialne za instalację /deinstalację serwisu (zaczynają sie od podkreślnika)

Tabela "CustomAction"

Rys.3. Zawartość tabeli "CustomAction"

Natomiast w tabeli "InstallExecuteSequence" znajdziemy sekwencje, którym przypisane są kolejno poszczególne akcje. Odszukujemy naszą "akcję" i sprawdzamy zawartość rekordu "Condition":  

Zawartość tabeli "InstallExecuteSequence"

Rys.4. Zawartość tabeli "InstallExecuteSequence"

Mamy tu następujący zapis "$C__A86DDC61F5864695A26A870927B7E6A3>2", z którego wynika, że akcja jest wykonywana gdy, komponent "C__A86DDC61F5864695A26A870927B7E6A3" ($ wskazuje na komponent), zawierający plik "StartAppsEWX.exe", jest dostępny w systemie lub uruchamiany bezpośrednio ze źródła instalacji (wartość > 2, oznacza, że może przyjmować stany 3 i 4).

Poniższa tabela zawiera możliwe stany dla komponentów i "ficzerów" stosowane przy definiowaniu kondycji. 

Stan (State)Wartość (Value)Znaczenie (Meaning)
INSTALLSTATE_UNKNOWN-1Akcja nie będzie wykonywana na komponencie lub "ficzerze".
INSTALLSTATE_ADVERTISED1Tylko w przypadku istnienia zaanonsowanych "ficzerów". Stan niedostępny dla komponentów.
INSTALLSTATE_ABSENT2"Ficzer" lub komponent nie istnieje.
INSTALLSTATE_LOCAL3"Ficzer" lub komponent znajduje się na lokalnym komputerze.
INSTALLSTATE_SOURCE4"Ficzer" lub komponent jest uruchamiany z plików źródłowych.
 

Rozwiązanie

1. Otwieramy pakiet do edycji w programie Orca i tworzymy transformację (menu "Transform" -> "New Transform")

2. Przechodzimy do tabeli "CustomAction" i usuwamy wszystkie akcje powiązane z naszym serwisem

Zawartość tabeli "CustomAction" po modyfikacjach

Rys.5. Zawartość tabeli "CustomAction" po modyfikacjach

3. Analogicznie postępujemy w tabeli "InstallExecuteSequence"

Zawartość tabeli "InstallExecuteSequence" po modyfikacjach

Rys.6. Zawartość tabeli "InstallExecuteSequence" po modyfikacjach

4. Następnie w tabeli "ServiceInstall" uzupełniamy następujace rekordy

Nazwa rekorduWartośćOpis
ServiceInstallAppGłówny klucz (Primary key) tabeli - dowolna nazwa
NameappNazwa serwisu
DisplayNameApp Client ServiceNazwa serwisu używana do identyfikacji przez inne programy
ServiceType16Typ serwisu, wartość "16" oznacza 32-bitowy serwis, który jest uruchamiany we własnym procesie
StartType2Flaga identyfikujaca w jaki sposób uruchamiany jest serwis. Wartość "2" oznacza, że serwis jest uruchamiany przy starcie systemu
ErrorControl1Określa sposób obsługi błędu, podczas uruchamiania serwisu. Wartość "1" oznacza , że informacja o napotkanym błądzie zapisywana jest do logu systemowego. Dodatkowo wyświetlany jest komunikat z treścią błędu i kontynuowana jest operacja uruchomienia serwisu.
Component_C__A86DDC61F5864695A26A870927B7E6A3Wskaźnik do komponentu
DescriptionApp ServiceOpis serwisu

Zawartość tabeli "ServiceInstall" po modyfikacjach

Rys.7. Zawartość tabeli "ServiceInstall" po wprowadzeniu danych

5. W tabeli "ServiceControl" uzupełniamy kolejno następujące rekordy

Nazwa rekorduWartośćOpis
ServiceControlappGłówny klucz (Primary key) tabeli - dowolna nazwa
NameappNazwa serwisu
Event160Operacje wykonywane na serwisie podczas instalacji\deinstalacji produktu (wartość "160" oznacza, że serwis jest zatrzymywany i usuwany podczas deinstalacji)
Wait0Wartość "0" wymusza pause na instalatorze, aż do momentu kiedy SCM (Service Control Manager) powiadomi o tym, że serwis jest w stanie oczekiwania na kolejne instrukcje.
Component_C__A86DDC61F5864695A26A870927B7E6A3Wskaźnik do komponentu
 

Zawartość tabeli "ServiceControl" po modyfikacjach

Rys.8. Zawartość tabeli "ServiceConrol" po wprowadzeniu danych

6. Zapisujemy transformację (menu "Transform" -> "Generate Transform…")  i testujemy instalację, reperację oraz deinstalację pakietu.

Be Sociable, Share!