AccessViolationException при входе в профиль MAPI

Частью нашего приложения является процесс Windows, который входит в систему MAPI и индексирует электронную почту в фоновом режиме. Он хорошо работает со многими различными версиями Outlook, а еще несколько дней назад использовался для работы с Outlook 2016. Теперь он выдает исключение AccessViolationException при входе в профиль MAPI.

Это сообщение об исключении:

Exception thrown at 0x00007FFDA7716BB9 (Mso20win32client.dll) in Tray.exe: 0xC0000005: Access violation writing location 0x0000000000000000.

Мы еще не смогли выяснить, почему он пытается получить доступ к этому местоположению. Насколько мы можем судить, все аргументы верны.

Стек вызовов выглядит так (у нас нет символов для dll Outlook):

 Mso20win32client.dll!00007ffda7716bb9()    Unknown
 OLMAPI32.DLL!00007ffda48e325e()    Unknown
 OLMAPI32.DLL!00007ffda48274e1()    Unknown
 OLMAPI32.DLL!00007ffda4827466()    Unknown
 OLMAPI32.DLL!00007ffda4827408()    Unknown
 OLMAPI32.DLL!00007ffda4827317()    Unknown
 CONTAB32.DLL!00007ffdee6a14f6()    Unknown
 OLMAPI32.DLL!00007ffda482670c()    Unknown
 OLMAPI32.DLL!00007ffda48261cd()    Unknown
 OLMAPI32.DLL!00007ffda48253c6()    Unknown
 OLMAPI32.DLL!00007ffda481653c()    Unknown
 OLMAPI32.DLL!00007ffda4815dc8()    Unknown
 MSMAPI32.DLL!00007ffdef225ee6()    Unknown
 [External Code] 

Есть несколько сообщений, в которых говорится о подобных проблемах, в частности, одна из них, которая кажется актуальной, — это это на Experts Exchange, но мы до сих пор не смогли определить основную причину или причину исправить.

Интересно, что всплески (тестовые программы), созданные для сужения проблемы, не обнаруживают проблему. Также хорошо работает MFCMAPI, который является инструментом для визуализации информации MAPI, т.е. мы можем входить в те же профили, используя его.

Кто-нибудь еще видел подобную проблему? Любые идеи о том, как отлаживать дальше?


person floatingfrisbee    schedule 08.11.2016    source источник


Ответы (1)


Вы загружаете olmapi32.dll. Не делайте этого - загрузите msmapi32.dll.

person Dmitry Streblechenko    schedule 08.11.2016
comment
Дмитрий, наш код вызывает MAPILogonEx со следующими флагами: MAPI_EXTENDED | MAPI_UNICODE | MAPI_EXPLICIT_PROFILE | MAPI_BG_SESSION | MAPI_NEW_SESSION, и это ведет к стеку вызовов, описанному выше, где вызов действительно проходит через MSMAPI32.dll, а затем в OLMAPI32.dll. Что мы можем сделать по-другому? Также это работало без каких-либо изменений до нескольких дней назад. - person floatingfrisbee; 09.11.2016
comment
Кроме того, мы используем подход библиотеки-заглушки MAPI, имея в нашем проекте MapiStubLibrary.cpp и StubUtils.cpp, как описано здесь: msdn.microsoft.com/en-us/library/office/cc963763.aspx - person floatingfrisbee; 09.11.2016
comment
Итак, загружается ли olmapi32.dll вызовом MAPILogonEx или он загружался раньше, когда вы динамически загружали msmapi32.dll и/или вызывали MAPIInitialize? - person Dmitry Streblechenko; 09.11.2016
comment
Похоже, что OLMAPI32.dll загружается в результате вызова метода MAPIInitialize. - person floatingfrisbee; 09.11.2016
comment
Также найдено статья, посвященная той же проблеме. После прочтения этой статьи мы обнаружили, что проблема возникает, когда мы вызываем MAPILogonEx в потоке, отличном от MAPIInitialize. На первый взгляд кажется, что это проблема, но, как я сказал в вопросе, этот код работал много месяцев во многих разных версиях Outlook и только недавно начал давать сбой в Outlook 2016. - person floatingfrisbee; 09.11.2016
comment
Вы действительно это делаете? Вам нужно вызвать MAPIInitialize как в основном потоке, так и во вторичном потоке, где вы вызываете MAPILogonEx. - person Dmitry Streblechenko; 10.11.2016
comment
Интересно, что все это время код работал, хотя мы не гарантировали, что MAPIInitialize будет вызываться в каждом потоке, вызывающем MAPILogonEx. Мы вызвали MAPIInitialize с флагом MAPI_MULTITHREAD_NOTIFICATION и, может быть, поэтому? А затем обновление Office 2016 привело к его поломке. Несмотря на это, мы реализуем решение, которое гарантирует, что MAPIInitialize вызывается в каждом потоке, который будет вызывать MAPILogonEx. Если у вас есть какие-либо дополнительные ошибки, о которых вы знаете, сообщите нам об этом. - person floatingfrisbee; 10.11.2016
comment
MAPI_MULTITHREAD_NOTIFICATION просто означает, что вы позволяете MAPI уведомлять вас о потоках, отличных от основного. MAPIInitialize по-прежнему должен вызываться в каждом потоке. - person Dmitry Streblechenko; 10.11.2016