1. Accessing anything in the Outlook Object Model. OutlookSpy seems to provide direct access to only a few objects in the Outlook Object Model. How do I access other objects? E.g. I want to look at the first recipient of a mail item, how do I do that?
2. Executing Outlook commands not available through its Object Model. I have noticed that there are quite a few things you can do through the Outlook UI, unfortunately a lot of that functionality is not programmatically accessible. I know that I can simulate clicks on the buttons, but how do I find those buttons programmatically to begin with?
1. Comparing two messages. I have two messages (one is created by my code and another one is a native Outlook message); they look really similar, but Outlook doesn't seem to like the message I have created.
2. Figuring out which message properties have changed . I am changing things through the Outlook UI, but I have hard time figuring out which Extended MAPI properties actually change. E.g. I am adding a new entry to Outlook's distribution list, which Extended MAPI properties does Outlook modify?
3. Opening any object by its entry id. I can see a binary property and I suspect it is some kind of an entry id, how do I find out what it really is? Or: I can see a notification on the IMsgStore|Advise tab; it gives me an entry id, but I have no idea which object it belongs to.
4. How do I access invisible Outlook folders? I can access any visible Outlook folder by just selecting it through the Outlook UI and clicking the IMAPIFolder button, but how about other (invisible) folders?
5. Constructing arbitrary restrictions in Extended MAPI. Programmatically creating restrictions in Extended MAPI is never fun, can OutlookSpy help?
6. Using OutlookSpy features outside of OutlookSpy. I am creating a search folder using Extended MAPI and I want to see all the notifications immediately. Unfortunately there is no way to look at that folder right away. How can I do that? Does OutlookSpy provide any means to force it to display object properties window programmatically?
7. Copying properties from one object to another. I have two objects with different sets of properties and I want to copy one or more property from one object to another.
8. Importing/exporting messages. I know I can save a message in Outlook in the MSG format and then drag it to any folder either on the same or a different machine, but how about the messages invisible in Outlook (e.g. folder view descriptor messages)?
Accessing anything in the Outlook Object Model. OutlookSpy seems to provide direct access to only a few objects in the Outlook Object Model. How do I access other objects? E.g. I want to look at the first recipient of a mail item, how do I do that?
You can easily browse from a parent object to its child object in OOM. In case of a sub-property, select it and click Browse button. For example, if you have MailItem window open, selecting Attachments property and clicking Browse button will display a new window with all properties and functions of the Attachments object. In case of Recipients, you can select the Recipients property, click Browse. In the new window go to the Functions tab, select Item function, click Call. Enter 1 as a parameter, click Ok. OutlookSpy will display the first Recipient of a given message.
An even easier way would be (if you don't mind some scripting) to go to the Script tab, type the script below, and click Run:
BrowseObject(MailItem.Recipients.Item(1))
Executing Outlook commands not available through its Object Model. I have noticed that there are quite a few things you can do through the Outlook UI, unfortunately a lot of that functionality is not programmatically accessible. I know that I can simulate clicks on the buttons, but how do I find those buttons programmatically to begin with?
If any given OOM object has a property named CommandBars, OutlookSpy will display an additional tab - CommandBars. An example would be opening an Explorer or an Inspector object. The CommandBars tab will display all CommandBars and their child buttons in a treeview. Once you drill down to the button you are after, simply select it and click Browse button. For example, you can find out that the the id of the "Send/Receive" button is 5488. You can use this value to programmatically find that button and simulate a click on it.
Set Btn = Application.ActiveExplorer.CommandBars.FindControl(1, 5488)
Btn.Execute
Comparing two messages. I have two messages (one is created by my code and another one is a native Outlook message); they look really similar, but Outlook doesn't seem to like the message I have created.
You can directly compare two messages - open both messages in OutlookSpy by clicking IMessage buttons. In one IMessage window, go to the Compare tab. Select PR_ENTRYID from the second message and drag it to the Compare tab of the first message. OutlookSpy will loop through all properties of each message and compare their values. OutlookSpy can display properties with different values, missing properties, extra, etc.
Figuring out which message properties have changed . I am changing things through the Outlook UI, but I have hard time figuring out which Extended MAPI properties actually change. E.g. I am adding a new entry to Outlook's distribution list, which Extended MAPI properties does Outlook modify?
When you open an IMessage window, OutlookSpy will install an advise sink(IMsgStore::Advise) to trap all notifications related to the currently displayed message. Go to the Watch tab of the IMessage window, select all properties you want to monitor and click the "->" button. Now whenever the message is modified (either through the Outlook UI after you save the changes or due to something else modifying the message), OutlookSpy will monitor fnevObjectModified notifications related to the message and compare old values of all properties with their new values after the modification. Modified properties will be logged in the window on the Watch tab.
Opening any object by its entry id. I can see a binary property and I suspect it is some kind of an entry id, how do I find out what it really is? Or I can see a notification on the IMsgStore|Advise tab; it gives me an entry id, but I have no idea which object it belongs to.
IMAPISession, IAddrBook, IMsgStore and IMAPIFolder windows have an OpenEntry tab. You can drag any PT_BINARY or PT_MV_BINARY property there and OutlookSpy will try to use it in a call to the OpenEntry() method of the corresponding object. Or, if you only have a hex representation of an entry id (e.g. as a result of a notification), you can click "Enter Entry ID Manually.." button and paste the hex value there.
Or, as a much quicker shortcut, you can select any PT_BINARY or PT_MV_BINARY property on a GetProp tab, right click on it and select IMAPISession::OpenEntry() from the popup menu.
How do I access invisible Outlook folders? I can access any visible Outlook folder by just selecting it through the Outlook UI and clicking the IMAPIFolder button, but how about other (invisible) folders?
You can browse to any folder of your choice (both visible and invisible in the Outlook UI) by opening the IMsgStore window and clicking the "Open Root Container" button. OutlookSpy will call IMsgStore::OpenEntry(0, NULL, ...). This will return the root folder of an IMsgStore. You can then go to the GetHierarchyTable tab of the root folder and open any of its child subfolders.
Constructing arbitrary restrictions in Extended MAPI. Programmatically creating restrictions in Extended MAPI is never fun, can OutlookSpy help?
You can let Outlook do the job: click "Tools | Advanced Find" in Outlook, create the appropriate restriction using the Outlook UI, click "Find". Outlook will create a temporary search folder.
Without closing the Advanced Find window (otherwise Outlook will delete the temporary search folder), browse to that folder from IMsgStore - click "Open Root Container", in the IMAPIFolder window go to the GetHierarchyTable tab, select the root search folder (e.g."Search Root" or "Finder" depending on whether you are using Exchange or PST), click "OpenEntry". In the new IMAPIFolder window go to the GetHierarchyTable again, open the last folder.
Search folder windows in OutlookSpy have an additional tab - GetSearchCriteria. That tab will display the search restriction you created using the Outlook UI. You can pretty much copy the text representation of the restriction and paste it into your code.
Using OutlookSpy features outside of OutlookSpy. I am creating a search folder using Extended MAPI and I want to see all the notifications immediately. Unfortunately there is no way to look at that folder right away. How can I do that? Does OutlookSpy provide any means to force it to display object properties window programmatically?
OutlookSpy does have an API that can be used to display its browser for any COM object it understands. You will need to create an instance of a OutSpy.Utils COM object and call Utils.BrowseObject(Object, ParentWnd) method. E.g. in VB:
set Utils = CreateObject("OutSpy.Utils")
Utils.BrowseObject(MyObject)
Copying properties from one object to another. I have two objects with different sets of properties and I want to copy one or more property from one object to another.
You can simply select any number of properties on one object (be that IMessage, IMAPIFolder or any other Extended MAPI object derived from IMAPIProp) and drop them on the GetProps tab of any another IMAPIProp descendant. OutlookSpy will call IMAPIProp::CopyProps() on the first object and then save the second object.
Importing/exporting messages. I know I can save a message in Outlook in the MSG format and then drag it to any folder either on the same or a different machine, but how about the messages invisible in Outlook (e.g. folder view descriptor messages or messages in folders other than the IPM tree)?
Saving a message in OutlookSpy is easy - just open any IMessage window and click the "Save as MSG file" button. You can then drag the saved message back to any of the Outlook's folders to create either a regular or an invisible (associated message) - simply open any IMAPIFolder window and drag the MSG file from Windows Explorer and drop it on the listbox either on the GetContentsTable or Associated Contents tab.