none
Exception while Enumerating GAL with large number of addressEntry RRS feed

  • Question

  • Recently I’m writing a customized SelectNamesDialog in Outlook 2010/Exchange 2010. In order to implement customized user search functionality,  I use GetGlobalAddressList and enumerate all the AddressEntries inside, everything works fine while the number of GAL entry is less than 500.

    However once the number of GAL entry increased, the enumerate job can NOT always successfully finished, more specifically the enumerate will:

    1. Stop at a random point (Normally while processing AddressEntry around 600 to 700)
    2. Then somehow after around few seconds Outlook start to prompt out “Outlook is trying to search data from …” at the right corner of the screen
    3. Finally an exception raised (Stack trace changes everytime, it can be any functions like retrieving a specific user attribute, etc.)

    _COMPlusExceptionCode      -532462766

    ErrorCode                                  -1664073723     

    Those Exception code and error code seems very common and it seems to me Exchange Server somehow refuse the request after a big amount of requests. I’ve tried to let the enumerate thread sleep 30 seconds once every 500 entries but no luck.

    I was thinking to issue might be due to Exchange Throttling Policy, however by checking PRCClientAccess logs on the CAS server, there's nothing been throttled.

    Then similar issues happens when I am tryting to count the number of a DL by using "AddressEntry.GetExchangeDistributionList().GetExchangeDistributionListMembers().Count", although technet memtioned "Expanding distribution lists can create a performance burden on an Exchange server, so use the GetExchangeDistributionListMembers method cautiously. Expect that your code will be slow when it expands large distribution lists." It's acceptable to get the result after a long while but its not expected to throw out an exception.

    Any ideas on these issues? Or other workaround for GAL search or DL member count is highly appreciated!

    Friday, April 19, 2013 8:34 AM

Answers

  • That's just a general CLR runtime error that's used for pretty much everything. It doesn't really help. Unless you're hitting some corrupted data or something where a permission issue is involved my guess is that you're still hitting some out-of-memory issue related to running out of RPC channels. I'd try Dmitry's suggestion of trying RDO, if that doesn't have any problems then there likely aren't any corruption or permissions issues.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Henry Y. Cheung" <=?utf-8?B?SGVucnkgWS4gQ2hldW5n?=> wrote in message news:5e3af54d-06f4-4825-aca5-4d1a3ce2216d...

    Ken, below is the excpetion:

    ==========================

    "Operation Failed"

    _COMPlusExceptionCode      -532462766

    ErrorCode                           -1664073723     

    ==========================

    The line of excpetion changes every time, but all of them contains COM object calling, most of the time are refer to below code:

    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress, exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);

    But even for that specifc line, the Call Stack could be different:

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_Department()
    at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_PrimarySmtpAddress()
       at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or something else...


    Henry Y. Cheung


    Ken Slovak MVP - Outlook
    Monday, April 22, 2013 3:57 PM
    Moderator
  • Also try to comment out most of your code (especially the ExchangeUser part) and see if that helps.

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

    Monday, April 22, 2013 4:28 PM
  • Dmitry, thanks for all your suggetions and comments, finally the reason has been found out, it's still due to throttling policy in Exchange 2010 which cause the issue, the resolution is simply run below command in EMS:

    Get-ThrottlingPolicy | Set-ThrottlingPolicy -RCAPercentTimeInAD 100 -RCAMaxConcurrency $null

    NOTE: I just turn those 2 properties to maximum, it might not need that much.

    Hope this can help someone else if who encounted similar issues in the future.


    Henry Y. Cheung

    Thursday, May 16, 2013 3:09 PM

All replies

  • You are probably running out of the RPC channels.

    What is your code? Are you using "foreach" enumerator? Keep in mind that foreach enumerator tends to keep all objects in the collection alive and there is no way to explicitly release them.


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

    Friday, April 19, 2013 7:37 PM
  • Dmitry, Thanks for your reply. I am not using "foreach" enumerator, below is the code of GALSearch for your reference:

    public static List<GALEntry> SearchGALOnline(string keywords)

            {

                List<GALEntry> galEntryResults = new List<GALEntry>();

                Outlook.AddressList gal = application.Session.GetGlobalAddressList();

                if (gal != null)

                {

                    try

                    {

                        int iTotalGALEntry = gal.AddressEntries.Count;

                        for (int i = 1; i <= iTotalGALEntry; i++)

                        {

                            Outlook.AddressEntry addrEntry = gal.AddressEntries[i];

                            if (addrEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry

                                                                  || addrEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)

                            {

                                Outlook.ExchangeUser exchUser = addrEntry.GetExchangeUser();

                                if (bIsUserMatchKeywordOnline(keywords, exchUser) == true)

                                {

                                    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress,

                                                                      exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);

                                    galEntryResults.Add(userEntry);

                                }

                            }

                        }

                    }

                    catch (Exception ex)

                    {

                        MessageBox.Show(ex.Message, "");

                    }

                }

                return galEntryResults;

            }

    Saturday, April 20, 2013 6:20 AM
  • You are using muleiple dot notation. The line

    Outlook.AddressEntry addrEntry = gal.AddressEntries[i];

    is equivalent to

    Outlook.AddressEntries addrEntries = addrEntry = gal.AddressEntries;

    Outlook.AddressEntry addrEntry = addrEntries.Item(I);

    And you cannot explicitly release addrEntries variable.

    Change your code to

    Outlook.AddressEntries addrEntries = addrEntry = gal.AddressEntries;
    for (int i = 1; i <= iTotalGALEntry; i++)
    {
        Outlook.AddressEntry addrEntry = addrEntries,Item(I);
        Outlook.ExchangeUser exchUser = addrEntry.GetExchangeUser();
        ...
        Marshal.ReleaseComObject(exchUser);
        Marshal.ReleaseComObject(addrEntry );
    }

    And donot forget to release all Outlook objects using Marshal.ReleaseComObject.

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



    Sunday, April 21, 2013 6:23 PM
  • Hi Dmitry, I've tried to modified the code based on your suggestions, but it's still not work. I've also tried to set COM object to null after using Marshal.ReleaseComObject, and explicted using GC.Collect() & WaitForPendingFinalizers() according to below article without success. :-(

    http://social.msdn.microsoft.com/forums/en-US/vsto/thread/a12add6b-99ea-4677-8245-cd667101683e/

    It stop at a random point (918 this time), then I saw "The thread '<No Name>' (0xefc) has exited with code 0 (0x0).", after around few seconds Outlook start to prompt out “Outlook is trying to connect server…”, then finally an exception raised. Sample output shown as below:

    ===========================================
    Number: 918 Start time: 4/22/2013 7:52:03 PM
    The thread '<No Name>' (0xefc) has exited with code 0 (0x0).
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in h3Olk.DLL

    ===========================================

    Below is the modified code:

    public static List<GALEntry> SearchGALOnline(string keywords)
    {
            List<GALEntry> galEntryResults = new List<GALEntry>();
            Outlook.AddressList gal = Globals.H3CAddIn.Application.Session.GetGlobalAddressList();
    
            if (gal != null) 
            { 
                    try
                    {
                        int iTotalGALEntry = gal.AddressEntries.Count;
                        Outlook.AddressEntries addrEntries = gal.AddressEntries;
    
                        for (int i = 1; i <= iTotalGALEntry; i++)
                        {
                            Outlook.AddressEntry addrEntry = addrEntries[i];
                            
                            Outlook.OlAddressEntryUserType addrEntryUserType = addrEntry.AddressEntryUserType;
    
                            if (addrEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry
                               || addrEntryUserType == Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
                            {
                                Outlook.ExchangeUser exchUser = addrEntry.GetExchangeUser();
    
                                //if (bIsUserMatchKeywordOnline(keywords, exchUser) == true)
                                if (true)
                                {
                                    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress,
                                                                      exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);
                                    galEntryResults.Add(userEntry);
                                }
    
                                Marshal.ReleaseComObject(exchUser);
                                exchUser = null;
    
                            }
    
                            Marshal.ReleaseComObject(addrEntry);
                            addrEntry = null;
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "");
                    }
                }
                return galEntryResults;
            }


    Henry Y. Cheung

    Monday, April 22, 2013 1:01 PM
  • Try declaring all of your Outlook objects such as Outlook.AddressEntry addrEntry, Outlook.ExchangeUser exchUser and any others outside of the for loop. Still release them inside the loop but that way you're only creating one such object instead of one per loop pass. See if that helps.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Henry Y. Cheung" <=?utf-8?B?SGVucnkgWS4gQ2hldW5n?=> wrote in message news:f6ba46db-e1fb-4cad-b463-11ba3a411351...

    Hi Dmitry, I've tried to modified the code based on your suggestions, but it's still not work. I've also tried to set COM object to null after using Marshal.ReleaseComObject, and explicted using GC.Collect() & WaitForPendingFinalizers() according to below article without success. :-(

    http://social.msdn.microsoft.com/forums/en-US/vsto/thread/a12add6b-99ea-4677-8245-cd667101683e/

    It stop at a random point (918 this time), then I saw "The thread '<No Name>' (0xefc) has exited with code 0 (0x0).", after around few seconds Outlook start to prompt out “Outlook is trying to connect server…”, then finally an exception raised. Sample output shown as below:

    ===========================================
    Number: 918 Start time: 4/22/2013 7:52:03 PM
    The thread '<No Name>' (0xefc) has exited with code 0 (0x0).
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in h3Olk.DLL

    ===========================================

    Below is the modified code:

    public static List<GALEntry> SearchGALOnline(string keywords)
    {
            List<GALEntry> galEntryResults = new List<GALEntry>();
            Outlook.AddressList gal = Globals.H3CAddIn.Application.Session.GetGlobalAddressList();
    
            if (gal != null) 
            { 
                    try
                    {
                        int iTotalGALEntry = gal.AddressEntries.Count;
                        Outlook.AddressEntries addrEntries = gal.AddressEntries;
    
                        for (int i = 1; i <= iTotalGALEntry; i++)
                        {
                            Outlook.AddressEntry addrEntry = addrEntries[i];
                            
                            Outlook.OlAddressEntryUserType addrEntryUserType = addrEntry.AddressEntryUserType;
    
                            if (addrEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry
                               || addrEntryUserType == Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
                            {
                                Outlook.ExchangeUser exchUser = addrEntry.GetExchangeUser();
    
                                //if (bIsUserMatchKeywordOnline(keywords, exchUser) == true)
                                if (true)
                                {
                                    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress,
                                                                      exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);
                                    galEntryResults.Add(userEntry);
                                }
    
                                Marshal.ReleaseComObject(exchUser);
                                exchUser = null;
    
                            }
    
                            Marshal.ReleaseComObject(addrEntry);
                            addrEntry = null;
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "");
                    }
                }
                return galEntryResults;
            }


    Henry Y. Cheung


    Ken Slovak MVP - Outlook
    Monday, April 22, 2013 1:54 PM
    Moderator
  • Hey Ken, I've tried with your suggestion, but unfortunately....still not working....

    ===========================================
    Number: 808 Start time: 4/22/2013 10:22:46 PM
    The thread '<No Name>' (0xc84) has exited with code 0 (0x0).
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in h3Olk.DLL

    ===========================================


    Henry Y. Cheung

    Monday, April 22, 2013 2:24 PM
  • Is Redemption as option?

    You can use RDOSession.AddressBook.GAL to retrieve RDOAddressList object, then call RDOAddressList.AddressEntries.MAPITable.ExecSQL to retrieve the data. Besides not opening each and every GAL object, it will also be an order of magnitude faster.


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

    Monday, April 22, 2013 2:33 PM
  • What exception are you getting, and on what line of code?
     
    I wouldn't worry about the thread exit information, I see that a lot in various addins with no ill effects.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Henry Y. Cheung" <=?utf-8?B?SGVucnkgWS4gQ2hldW5n?=> wrote in message news:f0294792-922c-4faa-8551-d12243671a9f...

    Hey Ken, I've tried with your suggestion, but unfortunately....still not working....

    ===========================================
    Number: 808 Start time: 4/22/2013 10:22:46 PM
    The thread '<No Name>' (0xc84) has exited with code 0 (0x0).
    A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in h3Olk.DLL

    ===========================================


    Henry Y. Cheung


    Ken Slovak MVP - Outlook
    Monday, April 22, 2013 2:57 PM
    Moderator
  • Ken, below is the excpetion:

    ==========================

    "Operation Failed"

    _COMPlusExceptionCode      -532462766

    ErrorCode                           -1664073723     

    ==========================

    The line of excpetion changes every time, but all of them contains COM object calling, most of the time are refer to below code:

    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress, exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);

    But even for that specifc line, the Call Stack could be different:

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_Department()
    at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_PrimarySmtpAddress()
       at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or something else...


    Henry Y. Cheung

    Monday, April 22, 2013 3:28 PM
  • Dmitry, I was aware of that product even before your first comment. :) And I've played around on OutlookSpy as well. Retreiving all the GAL members as well as DL members are so quickly and effectively in OutlookSpy made me believe that it's techinically workable. This plugin is for commercial usage thus the "developer version" is not suitable for us. The most important part is becasue we really want to figure out what the problem is because there could be lots of similar issues the predictable future for other functionality in this plugin dev job.

    I would be highly appreciated if you can give me some hints for how OutlookSpy or Redemption implement GAL enumalation...


    Henry Y. Cheung

    Monday, April 22, 2013 3:38 PM
  • That's just a general CLR runtime error that's used for pretty much everything. It doesn't really help. Unless you're hitting some corrupted data or something where a permission issue is involved my guess is that you're still hitting some out-of-memory issue related to running out of RPC channels. I'd try Dmitry's suggestion of trying RDO, if that doesn't have any problems then there likely aren't any corruption or permissions issues.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Henry Y. Cheung" <=?utf-8?B?SGVucnkgWS4gQ2hldW5n?=> wrote in message news:5e3af54d-06f4-4825-aca5-4d1a3ce2216d...

    Ken, below is the excpetion:

    ==========================

    "Operation Failed"

    _COMPlusExceptionCode      -532462766

    ErrorCode                           -1664073723     

    ==========================

    The line of excpetion changes every time, but all of them contains COM object calling, most of the time are refer to below code:

    GALEntry userEntry = new GALEntry(exchUser.Name, exchUser.Department, exchUser.PrimarySmtpAddress, exchUser.BusinessTelephoneNumber, exchUser.MobileTelephoneNumber, exchUser.OfficeLocation);

    But even for that specifc line, the Call Stack could be different:

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_Department()
    at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or

    at Microsoft.Office.Interop.Outlook._ExchangeUser.get_PrimarySmtpAddress()
       at H3Olk_Outlook_Plugin.GALUtility.SearchGALOnline(String keywords) in C:\Project\H3C Outlook Plugin\H3C Outlook Plugin\GALUtility.cs:line 90

    or something else...


    Henry Y. Cheung


    Ken Slovak MVP - Outlook
    Monday, April 22, 2013 3:57 PM
    Moderator
  • Also try to comment out most of your code (especially the ExchangeUser part) and see if that helps.

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

    Monday, April 22, 2013 4:28 PM
  • Dmitry, thanks for all your suggetions and comments, finally the reason has been found out, it's still due to throttling policy in Exchange 2010 which cause the issue, the resolution is simply run below command in EMS:

    Get-ThrottlingPolicy | Set-ThrottlingPolicy -RCAPercentTimeInAD 100 -RCAMaxConcurrency $null

    NOTE: I just turn those 2 properties to maximum, it might not need that much.

    Hope this can help someone else if who encounted similar issues in the future.


    Henry Y. Cheung

    Thursday, May 16, 2013 3:09 PM