none
Query IMessage from _ContactItem RRS feed

  • Question

  • Hi All,

    I have a stand alone application where I am trying to set a couple of MAPI properties, but I cannot seem to query the IMessage interface from a _ContactItem. I am using Outlook 2016 32-bit and 64-bit. I have not tested the 32-bit yet with this logic.

    STDMETHODIMP CRemoveFormDef::RemoveOneOff(IDispatch* dispOutlookContactItem, VARIANT_BOOL vbRemovePropDef)
    {
    	if (dispOutlookContactItem == nullptr)
    		return E_INVALIDARG;
    
    	CComPtr<_ContactItem> spContactItem;
    
    	HRESULT hr = dispOutlookContactItem->QueryInterface(__uuidof(_ContactItem), reinterpret_cast<LPVOID*>(&spContactItem));
    
    	if (FAILED(hr))
    		return hr;
    
    	CComPtr<IUnknown> spUnknown;
    	hr = spContactItem->get_MAPIOBJECT(&spUnknown);
    	if (FAILED(hr))
    		return E_FAIL;
    
    	CComPtr<IMessage> spMessage;
    	hr = spUnknown->QueryInterface(IID_IMessage, reinterpret_cast<LPVOID*>(&spMessage));
    	if (FAILED(hr)) /// <<< fails here
    		return hr;
    
    .
    .
    .
    

    No matter how I do it, I cannot seem to get the IMessage interface. However when I use Outlook Spy I seem to have no problem.

    I read I couple of articles mentioning to call MapiInitialize(), but that gives me an error complaining about the default mail program.

    Any thoughts are greatly appreciated.

    Thanks,

    Tom

    Wednesday, December 20, 2017 2:52 AM

Answers

All replies

  • Outlook 2013 (32 bit) -

    The QueryInterface call to obtain an IMessage interface pointer from a ContactItem when automating Outlook as an out-of-process server fails and returns HRESULT of E_FAIL.

    Since you want to use IMessage, have you considered going with Extended MAPI instead of automating Outlook?

    Wednesday, December 20, 2017 12:06 PM
  • Hi, Thanks for the answer. I should have remembered that! Yep, I will have to brush of the cob webs and dive into Extended MAPI again. I have been developing Outlook add-ins for so long that I completely forgot about that. :-) Thanks, Tom
    Wednesday, December 20, 2017 1:36 PM
  • You do need to call MAPIInitialize to be able to use any Extended MAPI functionality. If you get an error, that means you are loading a wrong dll - you must dynamically load msmapi32.dll. Take a look at the MFCMAPI source code to see how it is done.

    What exactly are you trying to do? Why do you need IMessage?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    • Proposed as answer by RLWA32 Wednesday, December 20, 2017 7:07 PM
    Wednesday, December 20, 2017 6:06 PM
  • Hi,

    My customer has an old C++ stand-alone application which uses an Outlook form (OFT). A previous developer did some repair code and caused a major issue which we are trying to come up with a fix. See this link

    https://msdn.microsoft.com/en-us/library/bb820932.aspx

    Wednesday, December 20, 2017 6:11 PM
  • As Dmitry Streblechenko suggested, after inserting a call to MapiInitialize, the QueryInterface for IMessage succeeded and returned an interface pointer using Outlook 2013 (32 bit).

    • Edited by RLWA32 Wednesday, December 20, 2017 7:12 PM
    Wednesday, December 20, 2017 7:09 PM
  • I still get the same error with Outlook 2016 64-bit with MFCMapi. I am not sure if this works with 64-bit versions. Can anybody confirm?


    • Edited by Thomas Lee3 Wednesday, December 20, 2017 7:13 PM
    Wednesday, December 20, 2017 7:11 PM
  • I have a .Net project calling my ATL DLL if anybody is wondering. I would be happy to sent my sample test DLL and EXE - compiled with VS 2015
    Wednesday, December 20, 2017 7:15 PM
  • What I did to get MAPI loaded for use with Outlook 2013 was to use the Outlook 2010 MAPI headers (previously downloaded) and the mapistublibrary..cpp and stubutils.cpp files from Stephen Griffin's mapistublibrary repo on github.  You can probably use the mapi header files and the above cpp files that are included with the MFCMAPI source at https://github.com/stephenegriffin/mfcmapi
    Wednesday, December 20, 2017 7:28 PM
  • Thanks, I am already using those headers. I am going to test my test application on my 2013 Outlook 32-bit VM and verify this works. So far, no joy on 64-bit
    Wednesday, December 20, 2017 7:32 PM
  • That simply means the bitness of MFCMAPI does not match the bitness of the MAPI system (Outlook).

    Try the 32 bit version of MFCMAAPI.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    • Marked as answer by Thomas Lee3 Thursday, December 28, 2017 10:58 PM
    Wednesday, December 20, 2017 7:54 PM
  • Yes the 32 bit version works.

    And my test program works with 32 bit versions of Outlook installed

    Wednesday, December 20, 2017 8:17 PM
  • Hi Dmitry and RLWA32,

    So I think, if understand correctly, 64-bit stand-alone applications are going to be a problem for Outlook 2013 & 2016. 

    We have an application that has been around for the better part of 15 years. This application was a 32-bit application (MFC - for the most part) and provided a COM interface that essentially managed a Outlook form. So the application would receive events from the form (OFT). For the most part, the events sent to the application would receive outlook contact items and query IMAPIProp, and manipulate properties. This works fine and has for the better part of the last almost two decades.

    So now the application was converted to a 64-bit (customer request to support 64-bit office) and we are finding that the existing functionality is not working in 64-bit - unable to query MAPI interfaces. So we are trying to come up with an interum solution.

    In the future we will put all this logic within a form region, and the application is slowy being converter to C#. But since the orginal application contains a huge amount of code, the process is slowly coming along.

    So I am asking for suggestions. What can I do to make sure the 64-bit application plays nice?

    Thanks,

    Tom


    • Edited by Thomas Lee3 Thursday, December 21, 2017 2:13 PM
    Thursday, December 21, 2017 2:09 PM
  • Not much you can do - you can create an auxiliary exe with the bitness that matches the bitness of the MAPI system (32 or 64 bit). That executable can then be launched from your main 64 bit exe.

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Thursday, December 21, 2017 2:26 PM
  • Just to be clear -

    After inserting the call to MapiInitialize (presumably returns S_OK) in a 64 bit test application that automates 64 bit Outlook the QueryInterface call still fails?

    Thursday, December 21, 2017 2:39 PM
  • Yes, that call fails. I am going to verify the return value of MapiInitialize. But I am pretty sure that passed. I will check
    • Edited by Thomas Lee3 Thursday, December 21, 2017 4:51 PM
    Thursday, December 21, 2017 4:46 PM
  • Ok, I have setup the test. 

    Test app - C# running as 64-bit

    ATL DLL - 64-bit

    Using Windows 10 with Office 2016 64-bit

    Using Outlook 2010 mapi headers

    1. The call to MAPIInitialize return S_OK

    2. QueryInterface for IMessage fails with a result of >> REGDB_E_IIDNOTREG Interface not registered

    Code below

    ////////////////////
    // C# TEST APP
    ///////////////////
    static void Main(string[] args)
    {
        Outlook.Application application = new Outlook.Application();
    
        var folder = application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
        // ATL DLL
        var remove = new CustomFormUtilLib.RemoveFormDef();
        remove.InitMapi();
        int i = 0;
        foreach (Outlook.ContactItem item in folder.Items)
        {
            remove.RemoveOneOff(item, true);
            Console.Write("*");
            i++;
        }
    
        remove.CleanupMapi();
    }
    
    
    //////////////////////////////
    // ATL DLL
    //////////////////////////////
    
    STDMETHODIMP CRemoveFormDef::InitMapi()
    {
    	MAPIINIT_0 MAPIINIT = { 0, MAPI_MULTITHREAD_NOTIFICATIONS };
    
    	HRESULT h = MAPIInitialize(&MAPIINIT);
    	if (SUCCEEDED(h)) 
    	{
    		m_bInitialized = true;
    	}
    	return S_OK;
    }
    
    
    STDMETHODIMP CRemoveFormDef::CleanupMapi()
    {
    	if(m_bInitialized)
    		MAPIUninitialize();
    	return S_OK;
    }
    
    STDMETHODIMP CRemoveFormDef::RemoveOneOff(IDispatch* dispOutlookContactItem, VARIANT_BOOL vbRemovePropDef)
    {
    	if (dispOutlookContactItem == nullptr)
    		return E_INVALIDARG;
    
    	CComPtr<_ContactItem> spContactItem;
    
    	HRESULT hr = dispOutlookContactItem->QueryInterface(__uuidof(_ContactItem), reinterpret_cast<LPVOID*>(&spContactItem));
    
    	if (FAILED(hr))
    		return hr;
    
    	CComPtr<IUnknown> spUnknown;
    	hr = spContactItem->get_MAPIOBJECT(&spUnknown);
    	if (FAILED(hr))
    		return E_FAIL;
    
    	CComPtr<IMessage> spMessage;
    	hr = spUnknown->QueryInterface(IID_IMessage, reinterpret_cast<LPVOID*>(&spMessage));
    	if (FAILED(hr))
    		return hr;
    
    
    	return S_OK;// RemoveItems(spMessage, vbRemovePropDef ? TRUE : FALSE);
    }
    
    
    
    

    Thursday, December 21, 2017 6:16 PM
  • What MAPI dll did you end up loading?

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Thursday, December 21, 2017 9:05 PM
  • I was using the stub library. I do not think it is working properly.

    So I am going to add the path functionality and load the library myself.

    I will let you know the out come after the holiday.

    Happy holidays!

    Friday, December 22, 2017 6:36 PM
  • The MAPIStubLibrary project on github (formerly codeplex) was not updated for Outlook 2016 as of this writing.

    That's why I suggested looking at the MAPIStubLibrary.cpp and StubUtils.cpp files from the MFCMAPI project on github.

    Happy Holidays to you, too. :)

    Friday, December 22, 2017 7:20 PM
  • Hi All,

    I finally had time to check this out further. I can load all the DLL's that MFCMAPI program finds in my program. In case you are interested, the following are all DLL's found (by my program and MFCMAPI).

    L"C:\\Program Files\\Microsoft Office\\root\\VFS\\ProgramFilesCommonX64\\system\\msmapi\\1033\\msmapi32.dll"
    L"C:\\Program Files\\Microsoft Office\\root\\Office16\\olmapi32.dll"
    L"mapi32.dll"
    L"C:\\Program Files\\Microsoft Office\\root\\VFS\\ProgramFilesCommonX64\\SYSTEM\\MSMAPI\\1033\\MSMAPI32.DLL"
    L"C:\\WINDOWS\\system32\\mapi32.dll"

    Bluntly, it seems like every DLL that I  load and I am able to call MapiInitialize and I can even login and get the session if I try - all that from my 64-bit process. So it seems like I can call any function in the mapi library.

    The problem I am having is when my ATL method receives a contact item (_ContactItem) from my .Net application, I try to query any MAPI interface from that interface (particulary querying IMessage and IMAPIProp) I get an error back of REGDB_E_IIDNOTREG. So the error is telling me that these interfaces are not registered, or need to be marshaled. So what I am thinking, is they were not registered properly for 64-bit, or I am dealing with a marshaling issue.

    This is the same problem I get from my Outlook form and my standalone contact manager. All 64 bit.

    So I am obviously missing something. I guess i will have to dig deeper, because in MFCMapi I can open the message item for the contact and in Outlook I can use Outlook Spy to open the message from a contact.

    Wednesday, December 27, 2017 8:21 PM
  • I wonder if this is the MAPI marshalling problem associated with the C2R bubble discussed at https://blogs.msdn.microsoft.com/stephen_griffin/2014/04/21/outlook-2013-click-to-run-and-com-interfaces/

    Perhaps Dmitry can address this possibility as he has the expertise in this area.

    • Marked as answer by Thomas Lee3 Thursday, December 28, 2017 10:58 PM
    Wednesday, December 27, 2017 9:32 PM
  • Hi RLWA32,

    You have solved the issue!!! Yippie kay yay!!! I would buy you a beer if you were here! :-)

    As soon as I ran the reg file (Outlook2013_C2R.reg) all my problems were solved. I am now able to query mapi interfaces from any application. 

    Thanks for the early New Years present.

    Thanks!!!!

    • Marked as answer by Thomas Lee3 Thursday, December 28, 2017 5:27 PM
    • Unmarked as answer by Thomas Lee3 Thursday, December 28, 2017 10:58 PM
    Thursday, December 28, 2017 5:18 PM
  • Hi RLWA32,

    You have solved the issue!!! Yippie kay yay!!! I would buy you a beer if you were here! :-)

    As soon as I ran the reg file (Outlook2013_C2R.reg) all my problems were solved. I am now able to query mapi interfaces from any application. 

    Thanks for the early New Years present.

    Thanks!!!!

    I'm happy that it all seems to have worked out well and I'll take a rain check for that beer. :)

    In the meantime, you might consider marking as answers any of the responses posted by Dmitry and by me that made substantial contributions towards arriving at the happy resolution.

    Thursday, December 28, 2017 6:02 PM