#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 снова изменил свои ключи. Теперь вы можете восстановить / удалить свою неудачную деинсталляцию.
Кроме того, я создал простое приложение-оболочку, которое устанавливает и запускает службу в СИСТЕМНОЙ учетной записи, а затем удаляет ее, как только она остановилась в конце процесса очистки.
Надеюсь, это поможет кому-нибудь с теми же проблемами, что и у нас здесь!