Ответ на исправление ошибки удаления MSI, вызывающей ошибку 2908 и исправленные разделы реестра «UNKNOWN Components»

#c# #windows #wix #registry #windows-installer

#c# #Windows #wix #реестр #windows-установщик

Вопрос:

Вопрос о неудачных деинсталляциях пакета MSI, приводящих к дальнейшим попыткам установки, возвращающим ошибку 2908 в журналах MSI (msiexec возвращает 1603), поднимался на очень многих разных форумах, поэтому я просто хотел предложить свое решение этой проблемы, поскольку у нас это появлялось время от времени на протяжении многих лет, и я никогда не видел программного решения для этого.

Основная причина заключается в том, что программа удаления MSI создает «потерянные ключи» в реестре в кусте LOCALMACHINE в разделе SOFTWARE Microsoft Windows CurrentVersion Installer UserData S-1-5-18 Components

Типичные ошибки журнала MSIEXEC выглядят следующим образом:

MSI (ы) (2C: 0C) [14:52:21:490]: Примечание: 1: 1401 2: НЕИЗВЕСТНЫЕ компоненты B44598ECC622C01BD780AEC8E234E3E1 3: 5 ОТЛАДКА: Ошибка 2908: не удалось зарегистрировать компонент {CE89544B-226C-B10C-7D08-EA8C2E433E1E}. MSI (ы) (2C: 0C) [14:52:21:523]: Продукт: Некоторое программное обеспечение 3.7 — Установщик столкнулся с неожиданной ошибкой при установке этого пакета. Это может указывать на проблему с этим пакетом. Код ошибки 2908. Аргументы следующие: {CE89544B-226C-B10C-7D08-EA8C2E433E1E}, ,

Как указывалось в других сообщениях, вы можете найти ключи из файла журнала MSI и отредактировать их с помощью Regedit, выполнить «свойства» и «дополнительно», изменить их владельца с «невозможно отобразить текущего владельца» (или аналогичный текст) на «Администраторы» и, наконец, установить права доступа к нему, как указано в этой ссылке:

https://kb.acronis.com/content/33458

Однако это громоздко, вы можете получить сотни неисправных элементов. Что еще хуже, у описанной выше ручной процедуры, похоже, есть проблемы в Windows 10, и инструмент «Windows Fixit» больше не доступен.

Итак, как это исправить автоматически? Эти «неработающие» разделы реестра трудно изменить даже с правами администратора, что приводит к различным ошибкам, поэтому, чтобы быть уверенным в успехе, я запускаю его как службу в СИСТЕМНОЙ учетной записи.

Таким образом, я создал проект службы Windows в Visual Studio, работающий от имени SYSTEM (SID S-1-5-18 ), затем мы открываем родительский ключ записей, вызывающих нарушение:

 RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);

RegistryKey regParent = hklm.OpenSubKey(
   "SOFTWAREMicrosoftWindowsCurrentVersionInstallerUserDataS-1-5-18Components",
   RegistryKeyPermissionCheck.ReadWriteSubTree,
   RegistryRights.FullControl);
  

Комментарии:

1. В чем вопрос?

2. Я ответил на свой собственный вопрос, который у меня был несколько дней назад, но никогда не писал здесь, поэтому я подумал написать информативный текст к ответу, который я придумал здесь, поскольку у многих людей есть вопросы по этому вопросу.

Ответ №1:

Поврежденные ключи могут быть обнаружены с помощью исключения securityexception при открытии каждого подраздела с

 regKey = regParent.OpenSubKey(
   registryKeyName,
   RegistryKeyPermissionCheck.Default,
   RegistryRights.TakeOwnership | RegistryRights.ReadPermissions | RegistryRights.ReadKey))
  

Для меня msiexec, похоже, добавил «Пользователя-администратора» для рассматриваемых поврежденных ключей, и что еще хуже, наследование правил по какой-то причине полностью перестало работать, я думаю, что именно по этой причине regedit не может показать владельца ключа, который на самом деле все еще СИСТЕМНЫЙ, поэтому ключи на самом деле не являются потерянными в первую очередь. Это также не помогает удалить RegistryAccessRule для этой странной записи пользователя Admin. Решение состоит в том, чтобы повторно применить правила для пользователей в regParent, поскольку это, похоже, также обновляет и «лечит» все дочерние узлы.

Таким образом, достаточно выполнить следующее:

    security = regParent.GetAccessControl(AccessControlSections.All);

    security.AddAccessRule(new RegistryAccessRule(
        new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null),
        RegistryRights.FullControl,
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
        PropagationFlags.None, // Self Children
        AccessControlType.Allow));

    security.AddAccessRule(new RegistryAccessRule(
        new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null),
        RegistryRights.FullControl,
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
        PropagationFlags.None, // Self Children
        AccessControlType.Allow));

    security.AddAccessRule(new RegistryAccessRule(
        new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null),
        RegistryRights.ReadPermissions | RegistryRights.ReadKey | RegistryRights.EnumerateSubKeys | RegistryRights.QueryValues,
        InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
        PropagationFlags.None, // Self Children
        AccessControlType.Allow));

    regParent.SetAccessControl(security);
  

Этого должно быть достаточно, чтобы Regedit заработал и Msiexec снова изменил свои ключи. Теперь вы можете восстановить / удалить свою неудачную деинсталляцию.

Кроме того, я создал простое приложение-оболочку, которое устанавливает и запускает службу в СИСТЕМНОЙ учетной записи, а затем удаляет ее, как только она остановилась в конце процесса очистки.

Надеюсь, это поможет кому-нибудь с теми же проблемами, что и у нас здесь!