none
Outlook addin - GetStorage - Incorrect function exception RRS feed

  • Question

  • Hi,

    I'm using StorageItem to save some internal information and I have problem with GetStorage method. We have mapped GetStorage to our custom programming language with GetStorage DispatchID.

    When using storage within only one folder, there is no problem. But when I try to get storage from another folder (from same or different datastore), I get exception "Incorrect function". I cannot induce exact behavior, only one thing I know is that is works everytime If there is no storage in target folder. 

    Example syntax:

    oFolder := oNameSpace.GetFolderFromID(OFolderID,'');
    if oFolder <> nil then begin
      oStorageItem := oFolderIndent.GetStorage('my.info', 0); // exception here
      if oStorageItem.Size = 0 then begin
        oStorageItem.UserProperties.Add('ID', 1);
      end;
      oID:= oStorageItem.UserProperties.Find('ID',true);
      oID.Value := 'xyz';
      oStorageItem.Save;
    end;

    Example situation:

    We have two datastores (.pst)
    First datastore has two calendars, lets call them "firstCal" and "secondCal"
    Second datastore has "thirdCal". Each calendar (folder) should have his unique storageItem.

    1. firstCal.GetStorage, returns storageItem with size 0, so I fill some userproperties
    2. firstCal.GetStorage, returns storageItem with size 1380, everything is fine
    3. thirdCal.GetStorage (or  secondCal.GetStorage) raises exception "incorrect function"
    4. calling thirdcal.GetStorage from visual studio works fine and after that, calling thirdcal.GetStorage from our app works too

    Any ideas how to solve this?

    Thanks. Michal



    • Edited by Wocko Tuesday, May 29, 2012 8:51 AM
    Tuesday, May 29, 2012 8:41 AM

Answers

  • Finally fixed thanks to this thread http://www.delphigroups.info/2/11/941254.html.

    "Delphi raises an error it is anything but S_OK (0), but VB(Visual Basic) checks if it is>0 (that's what SUCCEEDED macro/function does)."

    Our custom language is based on Delphi. GetStorage function call result was 1, and we were expecting S_OK (0) if call was ok.

    End of story.

    • Marked as answer by Wocko Thursday, August 2, 2012 8:14 AM
    Thursday, August 2, 2012 8:14 AM

All replies

  • what thread appartment is set on thread you are calling those function from? How do you instantiate outlook? is this add-in or external program? are you using multiple threads to access outlook API? 
    Tuesday, May 29, 2012 8:56 AM
  • In this situation, I'm calling GetStorage from external application. I can't give you exact information about thread policy, because I'm working on really big project and I don't know anything about this part (I don't work on this part). But if it is really important information, I can ask somebody who knows.

    I get instance of Outlook by calling TOutlookApplication.Create. TOutlookApplication is our class, which is connected through COM by its ClassID ({0006F03A-0000-0000-C000-000000000046}) and it's methods are connected by dispatchID.

    FYI we are using a lot of other functions and classes to communicate with outlook (we are synchronizing our app calendar with outlook's calendar) and it works fine. Nowadays we want to save some information to storageitem in selected folder.

    Tuesday, May 29, 2012 9:15 AM
  • you can check it yourself for example using debug option in VS, check Threads window. Please check if this code is invoked from the same thread that your TOutlookApplication.Create was called.
    Tuesday, May 29, 2012 9:42 AM
  • I'm pretty sure that TOutlookApplication.Create and GetStorage is called from same thread, because they are in same function.

    Here is whole code of my test function:

    Function : integer;
    var
      oStorageItem : TOutlookStorageItem;
      oFolderIndent: TOutlookMAPIFolder;
      oOutlook: TOutlookApplication;
      oNS: TOutlookNameSpace;
      
    Begin
      result := 1;
      oOutlook := TOutlookApplication.Create;
      try
        oNS := oOutlook.GetNameSpace('MAPI');
        oFolderIndent := oNS.GetFolderFromID('00000000EB4A232778CC9A4CA1DB8197E10954F622810000','');
          if oFolderIndent <> nil then begin
            oStorageItem := oFolderIndent.GetStorage('my.info', 0);
            result := ostorageitem.size;
          end;
      finally
        oNS.Logoff;
        oOutlook.Free;
      end;
            
    end.

    Tuesday, May 29, 2012 10:19 AM
  • could you verify that somewhere (maybe in Create function) actually Logon method on Session (namespace) is actually called? Or add such code just right after oOUtlook.GetNamespace("MAPI")
    Tuesday, May 29, 2012 10:42 AM
  • I've added logoff and logon to namespace and nothing has changed.

    oNS := oOutlook.GetNameSpace('MAPI');
    oNS.logoff;
    oNS.logon('','',false,false);

    As I mentioned before, communication with Outlook works perfectly (thousands lines of code which is synchronizing calendar events). Only GetStorage method doesn't work most of time.

    Tuesday, May 29, 2012 11:02 AM
  • You should never use a hard-coded EntryID or StoreID value, it will change as items or folders are moved and it will only ever be valid for tha specific folder in tha specific Store.
     
    oFolderIndent := oNS.GetFolderFromID('00000000EB4A232778CC9A4CA1DB8197E10954F622810000','');

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Wocko" <=?utf-8?B?V29ja28=?=> wrote in message news:e75e861f-d45c-4fbb-a95a-b0573f6f9d4c...

    I've added logoff and logon to namespace and nothing has changed.

    oNS := oOutlook.GetNameSpace('MAPI');
    oNS.logoff;
    oNS.logon('','',false,false);

    As I mentioned before, communication with Outlook works perfectly (thousands lines of code which is synchronizing calendar events). Only GetStorage method doesn't work most of time.


    Ken Slovak MVP - Outlook
    Tuesday, May 29, 2012 1:55 PM
    Moderator
  • You should never use a hard-coded EntryID or StoreID value, it will change as items or folders are moved and it will only ever be valid for tha specific folder in tha specific Store.
     
    oFolderIndent := oNS.GetFolderFromID('00000000EB4A232778CC9A4CA1DB8197E10954F622810000','');

    Ken Slovak MVP - Outlook

    I know. That piece of code is used for testing only (it is written above the code). And I dont think that's the problem, I'm calling GetStorage on not-null folder.

    I made a little workaround, I'm calling GetStorage in VS right before calling GetStorage in our app. It works, but I can't be satisfied with this.
    • Edited by Wocko Wednesday, May 30, 2012 6:06 AM
    Wednesday, May 30, 2012 5:40 AM
  • What do you mean that you "call GetStorage() in VS"? How are you calling that method in VS?

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Wocko" <=?utf-8?B?V29ja28=?=> wrote in message news:173bb9ea-8ad6-498c-b962-7ff7d01016ae...
    You should never use a hard-coded EntryID or StoreID value, it will change as items or folders are moved and it will only ever be valid for tha specific folder in tha specific Store.
     
    oFolderIndent := oNS.GetFolderFromID('00000000EB4A232778CC9A4CA1DB8197E10954F622810000','');

    Ken Slovak MVP - Outlook

    I know. That piece of code is used for testing only (it is written above the code). And I dont think that's the problem, I'm calling GetStorage on not-null folder.

    I made a little workaround, I'm calling GetStorage in VS right before calling GetStorage in our app. It works, but I can't be satisfied with this.

    Ken Slovak MVP - Outlook
    Wednesday, May 30, 2012 2:37 PM
    Moderator
  • What do you mean that you "call GetStorage() in VS"? How are you calling that method in VS?

    Ken Slovak MVP - Outlook

    I mean calling GetStorage method right from Outlook addin (made in Visual Studio), then calling GetStorage within our (extern) app. It seems to me storages is being locked or something, and GetStorage (called from Outlook addin) unlocks it somehow (then calling GetStorage in our app works).


    • Edited by Wocko Thursday, May 31, 2012 5:42 AM
    Thursday, May 31, 2012 5:41 AM
  • from description it seems like initialization with thread appartment issue (which determines marshaler), but someone would had to debug it.
    Thursday, May 31, 2012 8:59 AM
  • I will be very grateful if someone finds what's wrong.
    Friday, June 1, 2012 7:51 AM
  • Does your addin or the standalone code start with or request admin permissions? In the case of your addin, are you using the trusted Application object passed to you for deriving all of your Outlook objects?

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Wocko" <=?utf-8?B?V29ja28=?=> wrote in message news:89f32c1e-e3ab-49e1-ae20-a39302ca0bdf...
    I will be very grateful if someone finds what's wrong.

    Ken Slovak MVP - Outlook
    Friday, June 1, 2012 7:18 PM
    Moderator
  • I tried running our app as administrator and nothing has changed.

    In addin I'm using application provided by addin itself (this.Application), so I think it is trusted.

    But in our app (standalone), I'm using following code, which might be untrusted.

    oOutlook := TOutlookApplication.Create;
    oNS := oOutlook.GetNameSpace('MAPI');
    On the other hand, I'm using object (appoitment for example) properties, which should be read only in untrusted outlook application without problem. I verified it by modifying JournalItem body property, which should not be editable in untrusted mode (according to the table in this article http://codeidol.com/csharp/c-sharp-in-office/Working-with-Outlook-Objects/Outlook-Issues/) and it works well.

    So, even this is not the cause of my problem.


    • Edited by Wocko Tuesday, June 5, 2012 7:13 AM
    Tuesday, June 5, 2012 7:10 AM
  • Finally fixed thanks to this thread http://www.delphigroups.info/2/11/941254.html.

    "Delphi raises an error it is anything but S_OK (0), but VB(Visual Basic) checks if it is>0 (that's what SUCCEEDED macro/function does)."

    Our custom language is based on Delphi. GetStorage function call result was 1, and we were expecting S_OK (0) if call was ok.

    End of story.

    • Marked as answer by Wocko Thursday, August 2, 2012 8:14 AM
    Thursday, August 2, 2012 8:14 AM