У меня есть настроенное приложение настройки, которое устанавливает несколько файлов MSI. сегодня я попытался реализовать внешний пользовательский интерфейс, чтобы реализовать свой собственный индикатор выполнения, используя статью this. все выглядит нормально (progressbar получает данные и обновления), но примерно через 60% при запуске обновления компонентов я получаю исключение: «объект не установлен ...» и копание далее получил: _COMPlusExceptionCode «-532462766»MsiInstallProduct() запускает msiexe.exe, но в 32-битном режиме?
проверил монитор процесса и вдруг понял, что msiexec работает в 32-битном режиме.
смешно, когда вы вызываете msiexe напрямую, он начинается с 64 бит, но с использованием метода MsiInstallProduct() он начинается с 32 бит.
Я считаю, что исключение возникает, когда msiexec пытается настроить разделы реестра, а файлы MSI - на 64 бит.
любая помощь оценена.
Приветствия, Afshin
Update 1: включен журнал, используя MsiEnableLog и эта ошибка появилась:
«MSI (с) (94: F8) [07:50:29 : 395]: Внутреннее исключение во время операции установки: 0xc0000005 при 0x000007FE9827F768. "
Обновление 2: рытья дополнительно на основе предложению @marceln, используемый Process Monitor и заметил, есть два MSIexec процессов в памяти. один в 64-битном режиме, который находится в сеансе 0, а другой начинается с первого, когда я вызываю MsiInstallProduct. второй начинается с 'c: \ windows \ syswow64 \ msiexec.exe', который является 32-разрядной версией. Я попытался установить путь поиска, используя SetDllDirectory, но все равно получая тот же результат.
Update 3: основной процесс, безусловно, работает в 64-битном режиме: как prccess монитор доказывает это и результат команды PowerShell:
[reflection.assemblyname]::GetAssemblyName("setup.exe") | fl
Name : Setup
Version : 5.0.0.0
CultureInfo :
CultureName :
CodeBase : file:///...../Setup.exe
EscapedCodeBase : file:///Setup.exe
ProcessorArchitecture : **MSIL**
ContentType : Default
Flags : None
HashAlgorithm : SHA1
VersionCompatibility : SameMachine
KeyPair :
FullName : Setup, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null
Update 4: Я использую этот метод импорта msi.dll:
[DllImport("msi.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int MsiInstallProduct(string packagePath, string commandLine);
Update 5: Пробовал проводник процесса, приложение - 64 бит, файл MSI.DLL под приложением запускается из system32. но процесс msiexec.exe по-прежнему работает от syswow64, который составляет 32 бит. Файл msi построен как 64-битный msi.
Update 6: Я только что узнал, что эта линия является источником проблемы:
oldHandler = MSIIntrop.MsiSetExternalUI(
new MSIIntrop.InstallUIHandler(OnExternalUI),
32735,
IntPtr.Zero);
Update 7 [FINAL UPDATE]: Для кого это может касаться: После нескольких часов и часов тратить время, я, наконец, удалось преодолеть эту проблему. похоже, что в MSI API есть какая-то внутренняя утечка памяти, которая приводит к сбою внешнего обработчика пользовательского интерфейса в совершенно случайном поведении. Чтобы исправить эту проблему, я реализовал интерфейс IDisposable и попытался использовать класс в блоке «using», чтобы убедиться, что класс полностью удален. MsiSetExternalUI() и MsiInstallProduct() теперь безопасно вызываются внутри этого блока. не забудьте вызвать MsiSetExternalUI(), чтобы вернуть интерфейс в его исходное состояние:
IntPtr prevWindow = IntPtr.Zero;
MSIIntrop.INSTALLUILEVEL prevUILevel = MSIIntrop.MsiSetInternalUI(MSIIntrop.INSTALLUILEVEL.INSTALLUILEVEL_NONE, ref prevWindow);
using (MSIContext context = new MSIContext(progressChanged, messageRaised))
{
MSIIntrop.INSTALLUI_HANDLER prevHandlre = MSIIntrop.MsiSetExternalUI(context.Handler,
MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_FATALEXIT |
MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ERROR |
MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_WARNING |
MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_ACTIONDATA |
MSIIntrop.INSTALLLOGMODE.INSTALLLOGMODE_PROGRESS,
IntPtr.Zero);
try
{
int ret = MSIIntrop.MsiInstallProduct(runningPath, commandLine);
}
catch (Exception ex)
{
messageRaised("Error: " + ex.Message);
}
finally
{
MSIIntrop.MsiSetExternalUI(prevHandlre, 0, IntPtr.Zero);
}
}
PS 1: Я have't поставить это в ответ, так как я не% 100 уверен, что это был источник ошибки. Это всего лишь обходной путь. PS 2: Спасибо Марселю и Иаков :)
Тогда ваш хост-процесс должен быть 32 бит (тот, который называет 'MsiInstallProduct'). Вы проверили это? –
Да @marceln, у меня есть! хост-процесс - 64 бит, как я уже упоминал, если я запускаю msiexec.exe с использованием класса Process и передаю файл MSI в качестве аргумента, он запускается в режиме 64 бит. но с использованием MSI API и MsiInstallProduct начинается с 32 бит – Afshin
Затем используйте Dependency Walker, чтобы проверить, какая версия msi.dll (и его расположение) используется msiexec.exe. Затем убедитесь, что вы используете один и тот же из управляемого процесса. Кроме того, убедитесь, что ваш управляемый процесс построен с целью «Любой ЦП». –