none
strange user-defined field dasl issue switching from online mode to cached and vice versa RRS feed

  • Question

  • I have a dasl querty that I use to create a search folder for my add-in, I do this all in the code shown below.  one of the filter critera is a user-defined field.


                string ReceivedByName = addQuotes("http://schemas.microsoft.com/mapi/proptag/0x0040001E");
                string MyCustomField = addQuotes("http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/MyCustomField/0x0000001f");
                string MessageClass = addQuotes("http://schemas.microsoft.com/mapi/proptag/0x001a001e");
                string subject = addQuotes("urn:schemas:httpmail:subject");
                string MailDate = addQuotes("urn:schemas:httpmail:date");
                string fromName = addQuotes("urn:schemas:httpmail:fromname");

                filter = "(" + MyCustomField + " IS NULL";
                filter += " AND " + ReceivedByName + " IS NULL"; // this ensures that is not a received message
                filter += " AND " + fromName + " = '" + appInst.Session.CurrentUser.Name + "'";
                filter += " AND " + MessageClass + " LIKE '%IPM.Note%'";
                filter += " AND Not " + subject + "= 'Synchronization Log: '";
                filter += " AND " + MailDate + ">= '" + Now.AddDays(-7).ToString() + "')";

                // Start @ the MailBox folder to enable full breadth of search
               
                string searchRoot = appInst.Session.DefaultStore.GetRootFolder().FullFolderPath;

                StringBuilder sb = new StringBuilder();
                sb.Append("'");
                sb.Append(searchRoot);
                sb.Append("'");

                // Add custom property to folder
                string scope = sb.ToString();


                    appInst.AdvancedSearchComplete +=new Outlook.ApplicationEvents_11_AdvancedSearchCompleteEventHandler(appInst_AdvancedSearchComplete);
                    SearchFolderPopulating = true;
                    Outlook.Search search = appInst.AdvancedSearch(scope, filter, true, "My Custom");


                    search.Save("My Custom");
                    Outlook.Folder folder = appInst.Session.DefaultStore.GetSearchFolders()["My Custom"] as Outlook.Folder;

                    folder.ShowItemCount = Microsoft.Office.Interop.Outlook.OlShowItemCount.olShowTotalItemCount;
                    Outlook.NavigationPane pane = appInst.ActiveExplorer().NavigationPane;
                    Outlook.MailModule mailModule = pane.Modules.GetNavigationModule(Outlook.OlNavigationModuleType.olModuleMail) as Outlook.MailModule;
                    Outlook.NavigationGroup mailGroup = mailModule.NavigationGroups.GetDefaultNavigationGroup(Outlook.OlGroupType.olFavoriteFoldersGroup);
                    mailGroup.NavigationFolders.Add(folder);

     

    If I cerate this search folder in online mode it works fine, the query includes only items where my custom property is null.  If I switch to cache mode the search folder is oddly populated with items where my custom property is not null.  if I delete and re-create the folder while in cached mode the folder works as expected but when I switch back to online mode the folder is broken again.  Is it that my Custom property has a different internal id in cached vs online mode and the actual query that outlook creates when I pass in my dasl is expecting that value?


    Dan Budimir

    Friday, September 28, 2012 8:48 PM

Answers

All replies

  • What do you see if you look at the search criteria in OutlookSpy (go to that folder, click IMAPIFolder button, go to the GetSearchCriteria tab)?

    Are the two search criterias different? I have a vague recollection that Outlook reuses the named property tag in a store that has a different mapping.


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

    Friday, September 28, 2012 9:42 PM
  • Thanks Dmitry,

    They are indeed different.  All criteria for the internal fields are the same in both cached and online as below.

    rt : RES_AND
      cRes : 6
      lpRes :
        rt : RES_PROPERTY
        res.resProperty :
          relop : RELOP_GE
          ulPropTag : PR_CLIENT_SUBMIT_TIME (0x00390040)
          lpProp :
            ulPropTag : PR_CLIENT_SUBMIT_TIME (0x00390040)
            Value : 2:32 PM, 09/26/2012

        rt : RES_NOT
        res.resNot :
          lpRes :
            rt : RES_PROPERTY
            res.resProperty :
              relop : RELOP_EQ
              ulPropTag : PR_SUBJECT_A (0x0037001E)
              lpProp :
                ulPropTag : PR_SUBJECT_A (0x0037001E)
                Value : Synchronization Log:

        rt : RES_CONTENT
        resContent :
          ulFuzzyLevel : FL_SUBSTRING FL_IGNORECASE
          ulPropTag : PR_MESSAGE_CLASS_A (0x001A001E)
          lpProp :
            ulPropTag : PR_MESSAGE_CLASS_A (0x001A001E)
            Value : IPM.Note

        rt : RES_PROPERTY
        res.resProperty :
          relop : RELOP_EQ
          ulPropTag : PR_SENT_REPRESENTING_NAME_A (0x0042001E)
          lpProp :
            ulPropTag : PR_SENT_REPRESENTING_NAME_A (0x0042001E)
            Value : Budimir, Dan

        rt : RES_OR
          cRes : 2
          lpRes :
            rt : RES_NOT
            res.resNot :
              lpRes :
                rt : RES_EXIST
                res.resExist :
                  ulPropTag : PR_RECEIVED_BY_NAME_A (0x0040001E)
           
       
            rt : RES_PROPERTY
            res.resProperty :
              relop : RELOP_EQ
              ulPropTag : PR_RECEIVED_BY_NAME_A (0x0040001E)
              lpProp :
                ulPropTag : PR_RECEIVED_BY_NAME_A (0x0040001E)
                Value :

    but the custom parameter is different for cached vs online

    ONLINE

        rt : RES_OR
          cRes : 2
          lpRes :
            rt : RES_NOT
            res.resNot :
              lpRes :
                rt : RES_EXIST
                res.resExist :
                  ulPropTag : 0x844C (0x844C001E)
           
       
            rt : RES_PROPERTY
            res.resProperty :
              relop : RELOP_EQ
              ulPropTag : 0x844C (0x844C001E)
              lpProp :
                ulPropTag : 0x844C (0x844C001E)
                Value :

     

    CACHED

        rt : RES_OR
          cRes : 2
          lpRes :
            rt : RES_NOT
            res.resNot :
              lpRes :
                rt : RES_EXIST
                res.resExist :
                  ulPropTag : 0x8410 (0x8410001E)
           
       
            rt : RES_PROPERTY
            res.resProperty :
              relop : RELOP_EQ
              ulPropTag : 0x8410 (0x8410001E)
              lpProp :
                ulPropTag : 0x8410 (0x8410001E)
                Value :

    Any clue as to whats going on here and how to fix it?

    Thanks again for your time and input!


    Dan Budimir

    Friday, September 28, 2012 10:39 PM
  • If you click IMsgStore, then GetNamesFromIds, do these prop tags (0x844C001E vs 0x8410001E) match your custom property name?

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

    Friday, September 28, 2012 10:52 PM
  • in online mode

    propid: 0x8410
    lpropsetguid: {00020386-0000-0000-C000-000000000046}
    Mapped Name: x-sharing-local-type
    OOM Name - PidNameXSharingLocalType

    propid: 0x844c
    lpropsetguid: {00020329-0000-0000-C000-000000000046}
    Mapped Name: MyCustomProperty
    OOM Name - Not populated

    in cached mode

    propid: 0x8410
    lpropsetguid: {00020329-0000-0000-C000-000000000046}
    Mapped Name: MyCustomProperty
    OOM Name - Not populated

    propid: 0x844c - does not exist

    Thanks!


    Dan Budimir

    Monday, October 1, 2012 4:17 PM
  • So it looks like the search criteria is correct for each mode, right?

    Online - use 0x844c

    Cached - use 0x8410


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

    Monday, October 1, 2012 4:59 PM
  • Yes.  The only problem is that I have one search folder and it only works for one at a time.  Is there some way to force the propid to be the same in both cached or online so teh search folder will work in either mode?  Is there a better solution that you know of? 

    Dan Budimir

    Monday, October 1, 2012 5:15 PM
  • No, you have no control over the named property mapping.

    Did you post the search criteria of search folders that do work since they were explicitly created by your code or one of them is autocreated by Outlook when you change the cached mode setting?


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

    Monday, October 1, 2012 6:34 PM
  • I hope I'm understanding you correctly.  I only create one folder, my addin checks for the existence of my custom serach folder when ol starts.  If not found, it is created using the filter at the very top of this thread.  When switching from one mode to the next the search folder is not recreated because it already exists.  The autocreated folders are the same in both modes because their ids are fixed.  Did I understand the question?

    Dan Budimir

    Monday, October 1, 2012 7:08 PM
  • So when the search folder is recreated by Outlook after you switch mode, the prop tag in the search criteria is still the old one causing the problem, right?


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

    Monday, October 1, 2012 9:03 PM
  • The search folder is created once and never recreated.  Lets assume I start in online mode running my add-in for the first time.  The addin checks for the presence of the search folder and if it is not there creates it.  A week  later for one reason or another I go in to my data file properties and switch to cache mode and restart outlook.  The search folder is not recreated because it already exists.  The filter is now broken because ol has internally created a query that is looking for a prop tag of 0x844C for my user defined field which doesnt exist in cached mode, its now 0x8410.  If I now in cached mode delete the search folder and restart ol the search folder is recreated and works fine.  If I then switch back to online mode the filter is once again broken.


    Dan Budimir

    Tuesday, October 2, 2012 3:03 PM
  • Yep, that's what I assumed...

    I don't think you have much of a choice other than recreating the search folder: when Outlook creates a search (a hidden message with the message class of "IPM.Microsoft.WunderBar.SFInfo"), it stores the definition in a special blob. Everything is fine if you are using one of the templates. But if you are using a custom search, raw MAPI restriction (SRestriction structure) is stored; and SRestriction can only store the prop tags, bot the DASL names or the GUID/ids of the named props.

    You can use Redemption to look at the raw restriction of any Outlook search (RDOSearch.SearchCriteria property) to figure out if the prop tags are out of order: http://www.dimastr.com/redemption/rdosearch.htm


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

    Tuesday, October 2, 2012 4:38 PM
  • Hmmm.  So how about this for a fix.  Modify the filter to do an OR using the 2 valid prop tags for my user defined property.  This assumes that I can get and use the prop tag in my filter instead of the name.  Is it easy enough to get the prop tag using the fully qualified name and if so can I then use that prop tag in my query instead of the fully qualified name?  I'll then save off the prop tag.  On every start up I'll check the prop tag to see if it matches the last time I started, if not then add the new prop tag to the old one in my query, delete and re-create the search folder.  Sound ok?


    Dan Budimir

    Tuesday, October 2, 2012 9:43 PM
  • But your filter specifies the property name in the DASL format for the named property; the property tag is not hardcoded in the filter even though Outlook hardcodes it in SRestriction when it persists the search criteria.

    You can specify the property name in the fixed prop tag format (e.g. http://schemas.microsoft.com/mapi/proptag/8123001F) and use it in an OR expression for both cached and online modes, but that means you will need to know the prop tag for both modes ahead of time, which means (if you are in cached mode) that you will need to open the folder in the online mode using MAPI or Redemption. What if there is no online connection at that moment?

    And it is even worse if you are in the online mode - what if there is no cached store just yet?

    If I were you, I'd check the validity of the restriction first and then recreate the search if necessary.


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


    Wednesday, October 3, 2012 12:06 AM
  • Is there an easy fast way to retirieve the property tag using the name that I have given it?  If so I can store it and check every time the add in starts.  if the prop tag is different I can delete and recreate the folder with an OR using the old one and new.  The other wrinkle is that the search folder propagates to owa.  if the search folder created just to use cached mode propagates to owa it will be broken no matter what as owa is always in online mode.


    Dan Budimir

    Wednesday, October 3, 2012 4:23 PM
  • I don't think you can retrieve the property tag using OOM alone.

    You can use IMAPIProp::GetIDsFromNames() in MAPI or Safe*Item/RDOMail/RDOFolder/RDOStore/MAPIUtils.GetIdsFromNames in Redemption.

    The search folder in OWA will be broken no matter what you do - this is just an Outlook bug (or rather consider that a design flaw).


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

    Wednesday, October 3, 2012 4:40 PM
  • Thanks so much.  I trolled around a bit trying to find an exaple of how to use IMAPIProp::GetIDsFromNames() in c# to no avail.  Looks like a pInvoke is required.  Do you know of an example?


    Dan Budimir

    Wednesday, October 3, 2012 5:26 PM
  • You cannot use Extended MAPi in C#. There used to be a product called MAPI33 that allowed that, but I don't think it is supported/developed anymore.


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

    Wednesday, October 3, 2012 6:44 PM
  • So then Redemption is my only option?  I'm ok with that.  Just trying to make sure there are no other options before introducing a new component.

    Dan Budimir

    Wednesday, October 3, 2012 7:10 PM
  • Yes, unless you access IMAPIProp::GetIdsFromNames in C# or wrap that functionality in a C++/Delphi dll...

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

    Wednesday, October 3, 2012 9:50 PM
  • Thanks Dmitry.  That indeed was the answer so I added a c++ class lib to my solution.  As you may imagine I'm still struggling, while the function works fine and returns my porp tag, it does not fix my problem. 

    I have another question.  I've seen you comment about this question before but I'll ask again.

    Perhasps I need to start another thread, Moderator....

    I've opted to use 2 search folders, I label one as "online" the other "cache"

    Is there any way to hide a search folder in ol before it is activated?  If I can hide it before the user can activate it in online mode then the user will never be able to activate it.  If it is never activated it will never show up in owa.

    Also is there any way to prevent search folder from propagating?  If so this would prevent the folder from moving from the online store to the ost is the first place.

    As you can see, I'm coming to the end of my rope.  I really appreciate all of your time and input.


    Dan Budimir

    Wednesday, October 10, 2012 8:40 PM
  • I don't think there is a way hide a fodler in one more but not in another.

    You can hide a bormal folder, but I don't think you can do that with a search folder.


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

    Thursday, October 11, 2012 8:08 PM
  • Is there any event that fires when a search folder is created.  I know FolderAdd will not work.  Assume I've created a folder in online mode.  when the user starts up in cache mode it gets synced over.  Are there any events firing that I could handle when the search folder shows up?  The event does not have to be specifically tied to the search folder being created.  Just an event that I could use to check for its existence so I wouldnt have to use a timer.

    Dan Budimir

    Monday, October 15, 2012 7:24 PM
  • Folders.FolderAdd event should fire just fine on the top search folder. OOM does not expose it, but in Redemption you should be able to get it using RDOStore.SearchRootFolder

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

    Tuesday, October 16, 2012 2:26 AM