Я пишу программу, которая запускает MSI-установки без вывода сообщений в фоновом режиме. Используя MsiSetExternalUI и MsiSetInternalUI с INSTALLUILEVEL_NONE, я могу показать свое диалоговое окно прогресса и обнаружить ошибки во время установки:
INT CALLBACK ProgressHandler(LPVOID pvContext, UINT uiMessageType, LPCTSTR szMessage)
{
INSTALLMESSAGE iMessage = (INSTALLMESSAGE)(0xFF000000 & uiMessageType);
if( INSTALLMESSAGE_PROGRESS == iMessage )
ShowProgress(...);
if( INSTALLMESSAGE_FILESINUSE == iMessage )
MessageBox(NULL, szMessage, _T("Files in use"), MB_OK);
}
...
DWORD dwMessageFilter = INSTALLLOGMODE_PROGRESS | INSTALLLOGMODE_FILESINUSE;
MsiSetExternalUI(&ProgressHandler, dwMessageFilter, NULL);
INSTALLUILEVEL pervousUILevel = MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
UINT res = MsiInstallProduct(sPath, NULL);
Проблема в том, что когда некоторые файлы используются, мой обратный вызов получает сообщение INSTALLMESSAGE_FILESINUSE, но параметр szMessage содержит только этот текст - «Следующие приложения должны быть закрыты перед продолжением установки:». Если я запускаю msi-файл с полным интерфейсом, появляется диалоговое окно со списком программ, которые должны быть закрыты, прежде чем установка может быть продолжена.
Как получить этот список и отобразить его пользователю при запуске программы установки без пользовательского интерфейса?