Translate this site using Windows Live Translator:
Welcome to MSDN Blogs Sign in | Join | Help

Plug-In Sample to Synchronize Customization between Organizations

 

Hi all,

Here is a new Plug-In Sample proposition from my colleague Fouad Rachkidi:

- Scenario is having 2 or more organizations

- These organizations can be for testing, development, acceptance…

- You make schema customization on 1 organization and once you select “Publish All Customizations” the plug-in will be fired

- The plug-in will make a backup of the customization using the export message and a copy will be saved to disk (You can also make the backup before the publish is done Pre-PublishAll message)

- The exported file will be imported into a different organization using the import message

- Eventually both organizations will have the same schema, the plug-in is synchronizing any schema changes between the organizations.

Plug-In Registration Details:

<Register LogFile="Plug-in Registration Log.txt" Server="http://sqlcrmsrv:5555" Org="Acceptance" Domain="frachkid" UserName="crmadmin">
  <Solution SourceType="1" Assembly="ExportPublishImport.dll" Id="f6ec33d5-18f5-45d2-995c-bba5fda12443">
    <PluginTypes>
      <Plugin TypeName="ExportPublishImport.PluginClass" FriendlyName="c0f48c56-eeb5-48da-9bf0-c435ad4ddd14" Id="531f2c4a-7843-4bbe-af0d-33148bfea8a2">
        <Steps>
          <Step PluginTypeName="ExportPublishImport.PluginClass" PluginTypeFriendlyName="c0f48c56-eeb5-48da-9bf0-c435ad4ddd14" CustomConfiguration="" SecureConfiguration="" Description="PublishAll of none in Parent Pipeline" FilteringAttributes="" ImpersonatingUserId="" InvocationSource="0" MessageName="PublishAll" Mode="0" PrimaryEntityName="none" SecondaryEntityName="none" Stage="50" SupportedDeployment="0" Rank="1" Id="3ca8b544-bfce-de11-864c-00155dcd1a24">
            <Images />
          </Step>
        </Steps>
      </Plugin>
    </PluginTypes>
  </Solution>
</Register>


Plug-In Source Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Services.Protocols;
using System.IO;
 
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
 
using ExportPublishImport.ProductionCrmService;
 
namespace ExportPublishImport
{
    //Message: PublishAll
    //Primary Entity: None
    //Stage: Post 
    //Mode: Synchronous
    //Pipeline: Parent
    public class PluginClass : IPlugin
    {
        public void Execute(IPluginExecutionContext context)
        {
            try
            {
                if (context.MessageName.Equals("PublishAll"))
                {
                    //Exporting all customizations from test organization
                    ICrmService service = context.CreateCrmService(true);
                    Microsoft.Crm.SdkTypeProxy.ExportCompressedAllXmlRequest exportRequest = 
                        new Microsoft.Crm.SdkTypeProxy.ExportCompressedAllXmlRequest();
                    exportRequest.EmbeddedFileName = "All_CRM_Customizations.xml";
 
                    Microsoft.Crm.SdkTypeProxy.ExportCompressedAllXmlResponse exportResponse =
                        (Microsoft.Crm.SdkTypeProxy.ExportCompressedAllXmlResponse)
                        service.Execute(exportRequest);
 
                    byte[] compressedXml = exportResponse.ExportCompressedXml;
 
                    //Saving a backup copy 
                    using (FileStream fs = new FileStream(@"C:\Program Files\Microsoft Dynamics CRM\Customizations_Backup\AllCrmCustomizations.zip", FileMode.Create))
                    {
                        fs.Write(compressedXml, 0, compressedXml.Length);
                        fs.Close();
                    }
 
                    //Importing customization into a different organization
                    ProductionCrmService.CrmAuthenticationToken token = new ProductionCrmService.CrmAuthenticationToken();
                    token.AuthenticationType = 0;
                    token.OrganizationName = "Production";
 
                    ProductionCrmService.CrmService crmService = new ProductionCrmService.CrmService();
                    crmService.CrmAuthenticationTokenValue = token;
                    crmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
                    crmService.Timeout = 1000000;
 
                    ProductionCrmService.ImportCompressedAllXmlRequest importRequest =
                        new ProductionCrmService.ImportCompressedAllXmlRequest();
 
                    importRequest.CompressedCustomizationXml = compressedXml;
 
                    ProductionCrmService.ImportCompressedAllXmlResponse importResponse =
                        (ProductionCrmService.ImportCompressedAllXmlResponse) crmService.Execute(importRequest);
                }
            }
            catch (SoapException soapex)
            {
                throw new InvalidPluginExecutionException(soapex.Detail.InnerText);
            }
            catch (IOException ioex)
            {
                throw new InvalidPluginExecutionException(ioex.Message);
            }
        }
    }
}

Hope you’ll find this useful.

Regards

-Ben

Posted by benlec | 0 Comments

Cross Organization Contact Synchronization Plug-In Sample

Hi all

My colleague Fouad Rachkidi (CRM Escalation Engineer) who already posted another sample on this blog, created today a Pug-In which can allow you to create/update Contact across multiple Organization.

Ex: You created Contact1 in Org1, it gets automatically created in Org2.

It does also work on Updates of course, here are all the details and code.

Plugin Registration Information:

clip_image002

Plugin Registration XML:

<Register LogFile="Plug-in Registration Log.txt" Server="http://sqlcrmsrv:5555" Org="Org1" Domain="frachkid" UserName="crmadmin">
  <Solution SourceType="1" Assembly="IntegrationPlugin.dll" Id="3290a2ae-b3c0-4e13-a89d-605e9c58a5fd">
    <PluginTypes>
      <Plugin TypeName="IntegrationPlugin.IntegrationClass" FriendlyName="7a38185e-afd4-400a-b651-135783c44505" Id="48d50154-3ee5-4441-aca5-e52af2a5da82">
        <Steps>
          <Step PluginTypeName="IntegrationPlugin.IntegrationClass" PluginTypeFriendlyName="7a38185e-afd4-400a-b651-135783c44505" CustomConfiguration="" SecureConfiguration="" Description="Update of contact in Parent Pipeline" FilteringAttributes="" ImpersonatingUserId="" InvocationSource="0" MessageName="Update" Mode="1" PrimaryEntityName="contact" SecondaryEntityName="none" Stage="50" SupportedDeployment="0" Rank="1" Id="e47a6698-c7c2-de11-895a-00155dcd1a24">
            <Images>
              <Image EntityAlias="preEnityImageXml" ImageType="0" MessagePropertyName="Target" Attributes="" Id="41b818ab-c7c2-de11-895a-00155dcd1a24" />
              <Image EntityAlias="postEnityImageXml" ImageType="1" MessagePropertyName="Target" Attributes="" Id="157ae5b4-c7c2-de11-895a-00155dcd1a24" />
            </Images>
          </Step>
          <Step PluginTypeName="IntegrationPlugin.IntegrationClass" PluginTypeFriendlyName="7a38185e-afd4-400a-b651-135783c44505" CustomConfiguration="" SecureConfiguration="" Description="Create of contact in Parent Pipeline" FilteringAttributes="" ImpersonatingUserId="" InvocationSource="0" MessageName="Create" Mode="1" PrimaryEntityName="contact" SecondaryEntityName="none" Stage="50" SupportedDeployment="0" Rank="1" Id="a9cfab49-cac2-de11-895a-00155dcd1a24">
            <Images />
          </Step>
        </Steps>
      </Plugin>
    </PluginTypes>
  </Solution>
</Register>

Creating a new Contact in Org1….

clip_image002[5]

Contact created successfully in Org1…

clip_image002[7]

Same contact created in Org2 by the integration plugin.

clip_image002[9]

Now updating contact in Org1…

clip_image002[11]

Same contact in Org2 updated by the plugin.

clip_image002[13]

Plug-In Source Code :

using System;
using System.Collections.Generic;
using System.Text;
 
using IntegrationPlugin.Org1CrmSdk; //Web proxy for Org1 CrmService
using IntegrationPlugin.Org2CrmSdk; //Web proxy for Org2 CrmService
 
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
 
//This sample code provide integration between 2 organizations hosted on the same CRM server
//Org1 and Org2
//Creating a contact in Org1 will fire the IntegrationPlugin and the same contact is created in Org2
//Updating a contact in Org1 will fire the IntegrationPlugin and the same contact is updated in Org2
//This is only for demostation purposes of course the sample code can be extended further to add further integration requirements
//Also other entities can implement the same plug-in concept
 
namespace IntegrationPlugin
{
    public class IntegrationClass : IPlugin
    {
        public void Execute(IPluginExecutionContext context)
        {
            try
            {
                //    Message: Create
                //    Primary Entity: contact
                //    Sate: Post Stage
                //    Mode: Asynchronous
                //    Pipeline: Parent
                //    Deployment: Server
                if (context.InputParameters.Properties.Contains(ParameterName.Target)
                    && context.InputParameters.Properties[ParameterName.Target] is Microsoft.Crm.Sdk.DynamicEntity
                    && context.MessageName.Equals("Create"))
                {
                    Microsoft.Crm.Sdk.DynamicEntity entity = null;
 
                    entity = (Microsoft.Crm.Sdk.DynamicEntity)
                        context.InputParameters.Properties[ParameterName.Target];
 
                    if (entity.Name == Microsoft.Crm.SdkTypeProxy.EntityName.contact.ToString())
                    {
                        if (context.OutputParameters.Properties.Contains(ParameterName.Id))
                        {
                            //Retrieving the contactId of the contact created in Org1
                            Guid org1ContactId =
                                new Guid(context.OutputParameters.Properties[ParameterName.Id].ToString());
 
                            //Creating a Token for Org1
                            Org1CrmSdk.CrmAuthenticationToken org1Token = new Org1CrmSdk.CrmAuthenticationToken();
                            org1Token.AuthenticationType = 0;
                            org1Token.OrganizationName = "Org1";
 
                            //Creating an instance of the CrmService for Org1
                            Org1CrmSdk.CrmService org1CrmService = new Org1CrmSdk.CrmService();
                            org1CrmService.CrmAuthenticationTokenValue = org1Token;
                            org1CrmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
                            //Retriving the contact details from Org1
                            Org1CrmSdk.contact org1Contact = (Org1CrmSdk.contact)
                                org1CrmService.Retrieve(Org1CrmSdk.EntityName.contact.ToString(), org1ContactId, new Org1CrmSdk.AllColumns());
 
                            //Creating a Token for Org2
                            Org2CrmSdk.CrmAuthenticationToken org2Token = new Org2CrmSdk.CrmAuthenticationToken();
                            org2Token.AuthenticationType = 0;
                            org2Token.OrganizationName = "Org2";
 
                            //Creating an instance of the CrmService for Org2
                            Org2CrmSdk.CrmService org2CrmService = new Org2CrmSdk.CrmService();
                            org2CrmService.CrmAuthenticationTokenValue = org2Token;
                            org2CrmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
                            //Setting the details for the contact in Org2 based on the details of Org1 contact
                            Org2CrmSdk.contact org2Contact = new Org2CrmSdk.contact();
                            org2Contact.firstname = org1Contact.firstname;
                            org2Contact.lastname = org1Contact.lastname;
                            
                            //Creating the contact in Org2
                            Guid org2ConactId = org2CrmService.Create(org2Contact);
 
                            //Update contact in Org1 with the GUID of contact created in Org2
                            //Synch concept between the 2 contacts.
                            //We have a custom attribute so store the GUID
                            org1Contact.new_org2contactid = org2ConactId.ToString();
                            org1CrmService.Update(org1Contact);
                        }
                    }
                }
                //    Message: Update
                //    Primary Entity: contact
                //    Sate: Post Stage
                //    Mode: Asynchronous
                //    Pipeline: Parent
                //    Deployment: Server
                else if (context.InputParameters.Properties.Contains(ParameterName.Target)
                    && context.InputParameters.Properties[ParameterName.Target] is Microsoft.Crm.Sdk.DynamicEntity
                    && context.MessageName.Equals("Update"))
                {
                    //Preupdate image of the firstname and lastname
                    Microsoft.Crm.Sdk.DynamicEntity preEntityImage = null;
                    preEntityImage = (Microsoft.Crm.Sdk.DynamicEntity)context.PreEntityImages.Properties["preEnityImageXml"];
                    string preFirstName = (string)preEntityImage.Properties["firstname"];
                    string preLastName = (string)preEntityImage.Properties["lastname"];
 
                    //Postupdate image of the firstname and lastname
                    Microsoft.Crm.Sdk.DynamicEntity postEntityImage = null;
                    postEntityImage = (Microsoft.Crm.Sdk.DynamicEntity)context.PostEntityImages.Properties["postEnityImageXml"];
                    string postFirstName = (string)postEntityImage.Properties["firstname"];
                    string postLastName = (string)postEntityImage.Properties["lastname"];
                    string org2ContactId = (string)postEntityImage.Properties["new_org2contactid"];
 
                    //Creating a Token for Org2
                    Org2CrmSdk.CrmAuthenticationToken org2Token = new Org2CrmSdk.CrmAuthenticationToken();
                    org2Token.AuthenticationType = 0;
                    org2Token.OrganizationName = "Org2";
 
                    //Creating an instance of the CrmService for Org2
                    Org2CrmSdk.CrmService org2CrmService = new Org2CrmSdk.CrmService();
                    org2CrmService.CrmAuthenticationTokenValue = org2Token;
                    org2CrmService.Credentials = System.Net.CredentialCache.DefaultCredentials;
 
                    //Setting the details for the contact in Org2
                    Org2CrmSdk.contact org2Contact = new Org2CrmSdk.contact();
                    org2Contact.contactid = new IntegrationPlugin.Org2CrmSdk.Key();
                    org2Contact.contactid.Value = new Guid(org2ContactId);
                    if (!postFirstName.Equals(preFirstName))
                        org2Contact.firstname = postFirstName;
                    if (!postLastName.Equals(preLastName))
                        org2Contact.lastname = postLastName;
                    
                    //Update contact in Org2
                    org2CrmService.Update(org2Contact);
                }
            }
            catch (System.Web.Services.Protocols.SoapException soapex)
            {
                throw new InvalidPluginExecutionException("An error occurred in IntegrationPlugin", soapex);
            }
        }    
    }
}

Hope this helps

Benjamin LECOQ (Code & Idea by Fouad Rachkidi)

Posted by benlec | 0 Comments
Filed under: ,

Automatic Fix-It tool for KB968793 (Post UR installation changes)

Hi all,

The other day I installed UR6 on my box and hit this problem.
I found it annoying to go an modify my web.config myself. Also I remember many customers & partners hit this too. So.. I decided to create a tool to make it automatically.

Here is the interface:

clip_image002

How it works?

Well, the tool comes with an XML file containing the needed entries as specified in the KB.

There are 5 entries today in this file.

It offers two buttons, one for addition, one for removal and a status bar to notify the user about success/failure and the amount of entries modified.
Addition is safe and prevent any DUPLICATE problems. The tool compare the content of the Web.Config file and the content of the provided XML and perform a smart merge.
If entries are already there, the tool does nothing. If only one is needed, it will add this one, etc……

Same for removal, we will remove only the entries present in the provided XML.

Features:

  • Two buttons for addition or removal
  • Flexible tool (if one of the next CRM Update Rollup needs more authtypes, we can simply add them in the XML provided with the tool, no code change is required)
  • Safe :
    • it’s not possible to create duplicate entries when performing the addition. It’s not possible to remove un-wanted entries.
    • Before any action (add/remove) a backup file of the current web.config is created and restored In case of any exception.
  • More information button is redirecting you to the URL of the KB article.

Download:

Download CrmKB968793FixIt.zip from here, or go to the Download Page mentioned in the side column of this blog.

Usage:

Unzip the content of the archive anywhere locally on the CRM Server and execute the tool.

Archive content:

  1. MissingAuthTypes.xml
  2. CrmKB968793FixIt.exe

It’s possible in the near future that this will be integrated as a fix-it tool within the related KB article.
We are also check in front of the developer responsible for creating the UR installers to see if we can integrate this.

Kind Regards

Benjamin LECOQ

Microsoft Dynamics CRM 4.0 E-Mail Router unexpectedly stalls

 

Hi all,

It can happen that for no apparent reason the E-Mail Router sometimes stops working and you can receive the following error in the E-Mail Router machine Application Log:

#26234 - The E-mail Router service could not process a provider work item using assembly:
Microsoft.Crm.Tools.EmailProviders.dll and class: Microsoft.Crm.Tools.Email.Providers.ExchangePollingMailboxProvider.
System.Threading.ThreadAbortException: Thread was being aborted.
at Microsoft.Crm.Tools.Email.Agent.ServiceCore.ExecuteProviderWork(Object providerQueueRequestObject)
#14494 - A provider work item using assembly: 
Microsoft.Crm.Tools.EmailProviders.dll and class: Microsoft.Crm.Tools.Email.Providers.ExchangePollingMailboxProvider
has been aborted because it has been running for longer than the allowed execution time. 
This behavior may occur when there is a problem with the network or because the e-mail server is busy.
Verify that you can log on to the e-mail server by using an e-mail application that uses the account specified 
for the E-mail Router.
#26090 - An error occurred while opening mailbox crmemail@contoso.com. System.Net.WebException: The operation has timed out
at System.Net.HttpWebRequest.GetRequestStream()
at Microsoft.Crm.Tools.Email.Providers.HttpDavRequest.SubmitXmlCommand(HttpWebRequest httpWebRequest, String body)
at Microsoft.Crm.Tools.Email.Providers.HttpDavRequest.RetrieveInboxUri()
at Microsoft.Crm.Tools.Email.Providers.ExchangePollingMailboxProvider.OpenMailbox()
at Microsoft.Crm.Tools.Email.Providers.CrmPollingMailboxProvider.Run()

If you run the “Test Access” from the Configuration Manager you can also receive a timeout.

This is due to a lack of connections from a .Net perspective when we try to connect to Exchange via HttpDav. For more information, check the following article:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;915599

 

In order to resolve this issue please follow these steps :

On the CRM E-Mail Router machine, go to the following folder: %ProgramFiles%\Microsoft CRM Email\Server

1°) Right click on this file : Microsoft.Crm.Tools.Email.Management.config and open it in notepad.

Under the <Configuration> tag, add the following:

<system.net>
<connectionManagement>
<add address="*" maxconnection = "24" />
</connectionManagement>
</system.net>

Save the file.

2°) Still within the same folder, create a file called: Microsoft.Crm.Tools.EmailAgent.exe.config

Edit the file in Notepad and add this content:

<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection = "24" />
</connectionManagement>
</system.net>
</configuration>

Save the file and restart the E-Mail Router service (“NET STOP MSCRMEMAIL”, then “NET START MSCRMEMAIL” from a command line)

This should resolve this issue.

Kind regards

Benjamin LECOQ
CRM Escalation Engineer

Posted by benlec | 0 Comments

SDK Cleanup script for unwanted Workflow Instances stuck in Waiting… state

Hi all,

We regularly receive questions about how to get rid of many workflow instances stuck in Waiting state. 
You can cancel these workflow within the UI but for some reason this is sometime not suitable and executing a script is better.
Once these Workflow instances are canceled, you might need to perform a cleanup of the MSCRM Database.

Here is the code based on the SDK documentation my colleague Fouad Rachkidi (CRM Support Escalation Engineer) wrote:

   1: /*
   2: Microsoft provides programming examples for illustration only without warranty either expressed or implied.
   3: This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose
   4: This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures 
   5: Microsoft support engineers can help explain the functionality of a particular procedure. 
   6: However, they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements
   7: 
   8: You should install CRM 4.0 Rollup 3
   9: Also enable the registry keys part of KB 968755
  10: http://support.microsoft.com/kb/968755
  11: */
  12:  
  13: using System;
  14: using System.Collections.Generic;
  15: using System.Text;
  16: using System.Web.Services.Protocols;
  17: using CleanAsyncConApp.CrmSdk;
  18:  
  19: namespace CleanAsyncConApp
  20: {
  21:     class Program
  22:     {
  23:         static void Main(string[] args)
  24:         {
  25:             try
  26:             {
  27:                 CrmAuthenticationToken token = new CrmAuthenticationToken();
  28:                 token.AuthenticationType = 0; //AD authentication
  29:                 token.OrganizationName = "DIC"; //Organization Name
  30:  
  31:                 CrmService service = new CrmService();
  32:                 service.CrmAuthenticationTokenValue = token;
  33:                 service.Credentials = System.Net.CredentialCache.DefaultCredentials;
  34:                 service.UnsafeAuthenticatedConnectionSharing = true;
  35:                 service.Timeout = 3600000;
  36:                 
  37:                 ConditionExpression operationTypeCondition = new ConditionExpression();
  38:                 operationTypeCondition.AttributeName = "operationtype";
  39:                 operationTypeCondition.Operator = ConditionOperator.Equal;
  40:                 operationTypeCondition.Values = new object[1];
  41:                 operationTypeCondition.Values[0] = 10; //Workflow
  42:  
  43:                 ConditionExpression statusCodeCondition = new ConditionExpression();
  44:                 statusCodeCondition.AttributeName = "statuscode";
  45:                 statusCodeCondition.Operator = ConditionOperator.Equal;
  46:                 statusCodeCondition.Values = new object[1];
  47:                 statusCodeCondition.Values[0] = 10; //Waiting
  48:  
  49:                 FilterExpression queryFilter = new FilterExpression();
  50:                 queryFilter.FilterOperator = LogicalOperator.And;
  51:                 queryFilter.Conditions = 
  52:                     new ConditionExpression[] {operationTypeCondition, statusCodeCondition };
  53:  
  54:                 ColumnSet queryColumns = new ColumnSet();
  55:                 queryColumns.Attributes = 
  56:                     new string[] { "asyncoperationid", "operationtype", "statuscode"};
  57:  
  58:                 QueryExpression query = new QueryExpression();
  59:                 query.EntityName = EntityName.asyncoperation.ToString();
  60:                 query.Criteria = queryFilter;
  61:                 query.ColumnSet = queryColumns;
  62:                 query.PageInfo = new PagingInfo();
  63:                 query.PageInfo.PageNumber = 1;
  64:                 query.PageInfo.Count = 50;
  65:                 Console.WriteLine("CRM query created");
  66:  
  67:                 BusinessEntityCollection bec = service.RetrieveMultiple(query);
  68:                 Console.WriteLine("CRM query executed");
  69:                 Int64 counter = 0;
  70:  
  71:                 if (bec.BusinessEntities.Length > 0)
  72:                 {
  73:                     do
  74:                     {
  75:                         foreach (BusinessEntity be in bec.BusinessEntities)
  76:                         {
  77:                             asyncoperation async = (asyncoperation)be;
  78:                             async.statecode = new AsyncOperationStateInfo();
  79:                             async.statecode.Value = AsyncOperationState.Completed;
  80:                             service.Update(async);
  81:                             counter += 1;
  82:                         }
  83:                         query.PageInfo.PageNumber += 1;
  84:                         query.PageInfo.PagingCookie = bec.PagingCookie;
  85:                         bec = service.RetrieveMultiple(query);
  86:                     } while (bec.MoreRecords);

87: }

  88:                 else
  89:                 {
  90:                     Console.WriteLine("No workflows found with status waiting");
  91:                 }
  92:  
  93:                 if (counter != 0)
  94:                 {
  95:                     Console.WriteLine(counter + 
  96:                         " workflows have been updated with a state code completed");
  97:                 }
  98:             }
  99:             catch (SoapException soapex)
 100:             {
 101:                 Console.WriteLine(soapex.Detail.InnerText);
 102:             }
 103:             catch (Exception ex)
 104:             {
 105:                 Console.WriteLine(ex.Message);
 106:             }
 107:         }
 108:     }
 109: }

Once these Workflow status will change, you can clean the CRM MSCRM Database using the following script:

968520    Performance is slow if the AsyncOperationBase table becomes too large in Microsoft Dynamics CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;968520

More information:

AsyncOperationState Enumeration (CrmService)
http://msdn.microsoft.com/en-us/library/bb890231.aspx

Hope this helps.

Benjamin LECOQ

Posted by benlec | 1 Comments

How to troubleshoot [System Jobs] failures using [Advanced Find]

Microsoft Dynamics CRM 4.0 is using a lot of System Jobs to drive many features like: Send Bulk E-Mail, Import Data, Workflows, Duplicate Detections, Campaign Activities distribution, etc….. These jobs are processed by the Asynchronous Service and it can happen that the service fails to process these jobs. Jobs can fail or get stuck in waiting state. This is generally due to a configuration issue on the CRM Server.

Here are a few steps you can try to get more information about the System Jobs failures reasons and how to troubleshoot this:

Within the Microsoft Dynamics CRM Web Application, go to Settings \ System Jobs, click Advanced Find button, click Save As to save your custom query, name it “Troubleshooting System Job” for instance and click OK.

SaveAsTheView

Here you will need to add the two columns which will be helpful for troubleshooting. Click Edit Columns, Add Columns and select Error Code and Message. Click OK twice.

EditColumns

You will now get back to your view criteria (click Save to save the column change). Here you can for instance click Show Details and filter on the System Jobs which are showing errors (this is what we want), to do this, select the Error Code field and select Contains Data criteria.

ContainErrors1

You can also precise the query a little bit if you have more idea about the System Job type you are troubleshooting. Let say you want to troubleshoot Bulk Delete and Import File parse failures. Then filter on the System Job Type as shown on the screenshot.

ContainErrors

When you are done, click Find. The result will look like this:

Results3

You can see there the Message and Error Code column will give you the reason of the failure. The failure is likely to be that the Asynchronous Service cannot contact the CRM Web Services because of a bad configuration. It could be configuration within the MSCRM_CONFIG database or in the Server MSCRM Registry Hive. In this example above, the service cannot connect to the server named “WRONG”. Wrong was the name of the CRM Server i put in the AsyncSdkRootDomain value in my DeploymentProperties table.

Please have a look at the following articles for more information and for potential solutions:

950416    System Jobs are in a waiting state and Outlook clients cannot connect after you set the CRM Web site to an assigned IP address
http://support.microsoft.com/default.aspx?scid=kb;EN-US;950416

947423    How to update the Microsoft Dynamics CRM Web site port after you install Microsoft Dynamics CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;947423

950542    Synchronous plug-ins do not respond to the events that are triggered in Microsoft Dynamics CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;950542

 

Hope this helps.

Benjamin LECOQ

Deadlocks, Performance issues, MSCRM database growth, AsyncOperationBase table increase [Updated 03/12/09]

Hi all,

Performance issues can have many root cause and this article will not cover this.

For general CRM 4.0 Performance Optimization, the first thing you need to do is to go through are these documents:

Optimizing and Maintaining Microsoft Dynamics CRM 4.0
http://www.microsoft.com/downloads/details.aspx?FamilyID=ba826cee-eddf-4d6e-842d-27fd654ed893&displaylang=en

and also if you run SQL 2008:

Improving Microsoft Dynamics CRM Performance and Securing Data with Microsoft SQL Server 2008
http://www.microsoft.com/downloads/details.aspx?FamilyID=b5bb47a4-5ece-4a2a-a9b5-5435264f627d&DisplayLang=en

Apart from that, there are several hotfixes included in the Update Rollup 2 and 3 you should pay attention to.

The action plan to take advantage of these hotfixes and to maintain your CRM Database is the following:

A°) Install CRM 4.0 Update Rollup 3 (kb961768)
B°) Enable performance related Hotfixes (Pro-Active Action)
C°) Run additional cleanup script to address existing Database problems.

NOTE: About C°) before running SQL Cleanup scripts you might need to do a backup of your database in case you would run into any problem.
Also you shall ensure that you have the Max Degree Of Parallelism option greater than Zero (1 is just fine) if you are running a multi CPU SQL Server. This option is under the Advanced options of your SQL Server:

MaxDegree

Here is a list of Hotfixes and Articles you need to review:

B-1°) Performance can be affected because your AsyncOperationBase table contains millions of unnecessary records.

B-1.1°) Workflow related records (OperationType=10) cause the AsyncOperationTable and WorkflowLogBase table in the MSCRM database to grow too large

Fix included in Update Rollup 3, here is the related KB article:

968755    The AsyncOperationBase and WorkflowLogBase tables grow very large and performance issues occur when you use many workflows in CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;968755

Read this article carefully, you need to enable it via registry key.

And easy way to identify if you are running into this issue is to check how many records are in the AsyncOperationBaseTable by runnning a simple Count(*) and checking how many records you have of OperationType = ‘10’ and Succeeded/Completed.

Total count of records:

Select Count(*) from AsyncOperationBase

Total count of unnecessary records:

Select Count(*) from AsyncoperationBase Where OperationType = 10 AND StateCode = 3 AND StatusCode = 30

You can make a quick ration and see how bad you are affected by this.

There is a link in this KB to another article (KB968520) you need to execute the script mentioned there to cleanup your database. 

B-1.2°) KB957871 The Workflow Expansion Task records (Operation Type=1) cause the AsyncOperationTable table to grow too large in CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;957871

If you have the Update Rollup 2 or 3 you already have this hotfix, however it needs to be enabled via registry (please check the article).
Also note that this hotfix is Pro-Active only and prevent the issue to occur after fix installation. If your SQL Table is already full of these records you need to address this issue by running KB968520 clean-up scripts.
And easy way to identify if you are running into this issue is to check how many records are in the AsyncOperationBaseTable by runnning a simple Count(*) and checking how many records you have of OperationType = ‘1’ and Succeeded/Completed.

Total count of records:

Select Count(*) from AsyncOperationBase

Total count of unnecessary records:

Select Count(*) from AsyncoperationBase Where OperationType = 1 AND StateCode = 3 AND StatusCode = 30

You can make a quick ration and see how bad you are affected by this.


B-2°) SQL Blocking can occur if you are using E-mails heavily in CRM (ActivityParty, ActivityPointer tables contains millions of records)

KB959248 Microsoft Dynamics CRM 4.0 slows to unacceptable levels when you process e-mail messages by using the Microsoft Dynamics CRM E-mail Router
http://support.microsoft.com/default.aspx?scid=kb;EN-US;959248

If you have the Update Rollup 2 you already have this hotfix, in addition, the article also contains some SQL instructions you will need to follow to create INDEXES in order to improve performance (please check the article).

 

B-3°) MSCRM Database size is growing due to an increasing number of BulkDeleteIndependent_<GUID> tables

Under certain circumstances BulkDeleteIndependent_<GUID> temporary tables used by CRM to perform Bulk Delete operation are never deleted.
This issue has been fixed inside Update Rollup 2 however, there is no KB article associated with it.

Like scenario 1°) the hotfix is PRO-Active only and if you are already running into this issue, you will need to use the following SQL Cleanup script to remove the tables.

   1: -- Drop the Bulk Delete non metadata tables that had been created with [non-dbo] as owner. 
   2: -- This is to clean up any hanging tables during upgrade that were left due to a bug fixed in UR2
   3:  
   4: DECLARE @name varchar(255)
   5: DECLARE @dropCommand varchar(255)
   6:  
   7: DECLARE tableCursor CURSOR FAST_FORWARD FOR
   8:     SELECT '[' + SU.name + '].' + SO.name name FROM dbo.sysobjects SO, dbo.sysusers SU 
   9:     WHERE SO.xtype='U'AND SO.name LIKE 'BulkDelete%[_]%' AND SO.UId = SU.UId AND SU.name <> 'dbo'
  10:  
  11: OPEN tableCursor
  12:  
  13: FETCH next FROM tableCursor INTO @name
  14: WHILE @@fetch_status=0
  15: BEGIN
  16:     SET @dropcommand = N'drop table ' + @name
  17:     EXECUTE(@dropcommand)
  18:     FETCH next FROM tableCursor INTO @name
  19: END
  20:  
  21: CLOSE tableCursor
  22: DEALLOCATE tableCursor

 

B-4°) The data column of some AsyncOperationBase table records is not cleared once these records are completed.

This issue is similar to 1°) the PRO-Active hotfix is included in the Update Rolllup 2 however there is a need for a SQL Scripts to clear up manually the Data field of impacted records.

The related KB article is this one:

954929 Performance is poor when you change a user from one business unit to another in Deployment Manager in Microsoft Dynamics CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;954929

In order to know the number of records impacted by this issue, you can run the following script:

   1: select Count(*) from AsyncOperationBase Where
   2: (OperationType <> '17'    -- ImportingFile
   3: AND OperationType <> '23'  -- BulkDeleteChild
   4: AND OperationType <> '13') -- BulkDelete
   5: AND StateCode = '3'       -- Completed
   6: AND StatusCode = '30'     -- Succeeded
   7: AND Data is NOT NULL

In order to cleanup the Database from these records, we suggest you to run the script mentioned in KB968520

C°) General clean-up script you can run after you check above points:

968520 Performance is slow if the AsyncOperationBase table becomes too large in Microsoft Dynamics CRM 4.0
http://support.microsoft.com/default.aspx?scid=kb;EN-US;968520

NOTE: Once you will have checked all these steps, you might need to re-index and update the statistics of the two above mentioned tables.

- You must not do this during Working hours because it will take a lot of resources on the SQL Server.
- You need to ensure that the Recover Model is set to Simple during this operation to prevent the Log file to grow to much. This is a Database option

RecoveryModel

You can run the following script to perform this operation:

   1: -- Rebuild Indexes & Update Statistics on AsyncOperationBase Table
   2: ALTER INDEX ALL ON AsyncOperationBase REBUILD WITH
   3: (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)
   4: -- Rebuild Indexes & Update Statistics on WorkflowLogBase Table
   5: ALTER INDEX ALL ON WorkflowLogBase REBUILD WITH
   6: (FILLFACTOR = 80, ONLINE = OFF,SORT_IN_TEMPDB = ON, STATISTICS_NORECOMPUTE = OFF)

NB: Run one statement after the other, wait for the 1st one to complete before executing the other one

Hope this helps

Benjamin LECOQ

Improving CRM4 Performance under Windows 2008 using IIS7 Output Caching feature

Hi all,

Web content can be divided into two categories: static content and dynamic content. Static content does not change from request to request. The content that gets returned to the web browser is always the same. Examples of static content include HTML files, JPG or GIF files.

The other is dynamic content. This is the response that gets generated for dynamic content changes with every request. Examples include ASP.NET or PHP content.

There is a big range between these two categories which includes semi-dynamic content. Imagine a dynamic ASP.NET page that executes a database query. There is no reason to execute this query on every request if the underlying database tables change infrequently.

The IIS 7.0 Output Caching feature targets semi-dynamic content. It allows you to cache static responses for dynamic requests and to gain tremendous scalability.

I tried to use this feature on my CRM system and the result was quite good. This was not of course fully tested and I have no idea about the impact it can have on Multi-Org environment (sharing same aspx pages via redirection) and with multiple users of course. You need to TEST!

I’m waiting for your comments on this post to see how it’s going on for you and also if you would have some settings to propose.

Please read this if you want more information about this feature:
http://learn.iis.net/page.aspx/154/iis-7-output-caching/
http://learn.iis.net/page.aspx/380/improving-performance-with-native-output-caching/

Basically what you need to do is this:

1°) Open INETMGR, select Microsoft Dynamics CRM web site.
2°) On the Feature View you will have “Output Caching”, double click on it.
3°) On the Action pane, click on “Edit Feature settings”, make sure both cache and kernel cache are enabled and click OK.

Now you need to add your caching rule for the site, we will start at the Root level.

4°) Still at the Root of the Website under Output Caching, click ADD and set:

File Name Extension: bmp
Check Kernel Mode Caching
File Cache Monitoring: Using file change notifications

Click OK and ADD the same caching rule for css, gif, htc, js and png file extensions.

Add also another rule  slightly different for css.aspx pages. Click ADD and set:

File Name Extension: css.aspx
Check User-Mode Caching
File Cache Monitoring: Using file change notifications
Click Advanced, check Query String Variable(s): lcid

You should see something like this:

Capture

In the end the Output Caching Window shall look like this at the Root of the Website.

Output

5°) Now you can add other rules on the others sub folders of the web site, each time you need to select the folder and double click on Output Caching to add another rule.

Add this:

Folder: _forms
File Name Extension: js.aspx
Check User-Mode Caching
File Cache Monitoring: Using file change notifications
Advanced, Query String: etc,FormType,FormName

Folder: _root
File Name Extension: aspx
Check User-Mode Caching
File Cache Monitoring: Using file change notifications
Advanced, Query String: aspx group,area,subarea,etc,supresslink

Folder: Tools
File Name Extension: aspx
Check Kernel Mode Caching
File Cache Monitoring: Using file change notifications

If you have any problem with this, remove the rules, and/or disable the main feature.

Hope this helps and that you will find it interesting. Please let me know how it goes in your comments.

Benjamin LECOQ

Posted by benlec | 1 Comments

Incoming E-Mails are not Tracked in CRM

Hi all,

I’ve written a few blog posts to explain how to use tracing to troubleshoot E-Mail issues.
Here I would like to provide a series of steps to check in order to fix these issues without having to analyze any trace.

We assume that the CRM User or Queue we want to troubleshoot in CRM is using the Email Router to track Emails.
We assume also that the Test Access in the E-Mail Router Configuration Manager is working fine for this CRM User or Queue.

NB: If the above is not true, there will be soon a document on the Developer Blog to troubleshoot this.

1°) Check the CRM User / Queue properties (E-Mail Filtering Method/Incoming Profile/E-mail address/etc…).

  • For a CRM User, you need to log on the CRM Web Application as this CRM user and check in Tools \ Options \ E-Mail Tab.
    Make sure you have the proper settings here. Switch to “All e-mail messages” to facilitate troubleshooting.

PersonnalOptions

Also you can use the CrmServerReportInformation Log generated by the CrmDiagTool4.
Go to the section called “All Users Information”. Here you can find all the information you need to check (E-Mail Address, Incoming Profile, Filtering Method)

----------------SDK: All Users Information----------------
[Organization N°1............................]: TrevorsBangers
[ORG[1]USER[1] Fullname......................]: Peter Chimaera
[ORG[1]USER[1] DomainName....................]: TITAN\chimaera
[ORG[1]USER[1] Internal E-Mail Address.......]: chimaera@Titan.co.uk
[ORG[1]USER[1] Incoming Email DeliveryMethod.]: E-mail Router
[ORG[1]USER[1] Outcoming Email DeliveryMethod]: E-mail Router
[ORG[1]USER[1] Incoming Email FilteringMethod]: E-mail Router
[ORG[1]USER[2] Fullname......................]: John Griffith
  • For a QUEUE, you need to go to Settings \ Business Management \ Queues. Open your Queue record.

Make sure you have the proper settings here. Switch to “All e-mail messages” to facilitate troubleshooting.
Make sure all other settings are ok, the Email Address, the owner, the business unit, the Incoming profile.

NOTE: Make sure the owner of the Queue has a proper CRM Role assigned to him.

queue

Also you can use the CrmServerReportInformation Log generated by the CrmDiagTool4.
Go to the section called “All Public Queues Information”. Here you can find all the information you need to check.

----------------SDK: All Public Queues Information----------------
[Organization N°1......................................]: TrevorsBangers
[ORG[1]QUEUE[2] Queue Name.............................]: Support
[ORG[1]QUEUE[2] E-Mail.................................]: support@CRM4.com
[ORG[1]QUEUE[2] Business Unit..........................]: test
[ORG[1]QUEUE[2] Owner..................................]: First name Last name
[ORG[1]QUEUE[2] Convert to e-mail activities...........]: All e-mail messages
[ORG[1]QUEUE[2] E-Mail access type - Incoming..........]: E-mail Router
[ORG[1]QUEUE[2] E-Mail access type - Outgoing..........]: E-mail Router
[ORG[1]QUEUE[2] Allow credentials for the E-mail Router]: No

2°) Make sure the E-Mail Address used for your CRM User / Queue is not also used by other records (other CRM User, Account, Contact, Lead)

When CRM Receives an Email it needs to know to which CRM Record the Email will belong to. The Email received of course do not say if it is targeted to a Queue a Contact, a CRM user, etc…

So CRM needs to deal with the only information he has in the Email to perform the match: the Email Address of the recipient.

Ex: If CRM receives an email and the recipient is support@CRM4.com, it will search in the database who has an email address equal to support@CRM4.com.
If other records like an Account, Contact, User, Queue, Lead are also using support@CRM4.com in their email address field, the email will simply be rejected and will not be tracked in CRM at all.

In order to verify this, the quickest and easiest way is to do a search in the Organization Database using the following SQL Script:

declare @emailAddress as varchar(100)

set @emailAddress = 'email address to search for'


SELECT FullName, SystemUserId, InternalEmailAddress, PersonalEMailAddress 
FROM SystemUserBase
WHERE InternalEMailAddress = @emailAddress
OR PersonalEMailAddress = @emailAddress


SELECT Name, QueueId, EMailAddress 
FROM QueueBase
WHERE EMailAddress = @emailAddress

SELECT Name, AccountId, EMailAddress1, EMailAddress2, EMailAddress3 
FROM AccountBase
WHERE EMailAddress1 = @emailAddress
OR EMailAddress2 = @emailAddress
OR EMailAddress3 = @emailAddress

SELECT FullName, ContactId, EMailAddress1, EMailAddress2, EMailAddress3 
FROM ContactBase
WHERE EMailAddress1 = @emailAddress
OR EMailAddress2 = @emailAddress
OR EMailAddress3 = @emailAddress

SELECT Subject, LeadId, EMailAddress1, EMailAddress2, EMailAddress3 
FROM LeadBase
WHERE EMailAddress1 = @emailAddress
OR EMailAddress2 = @emailAddress
OR EMailAddress3 = @emailAddress

Usage: Change the following part to match the Email Address you are searching.

Example:

set @emailAddress = 'support@CRM4.com'

Run the search against your XXXX_MSCRM Organization Database and check if you have more than ONE result. Check if the other place where this email address is used is a User or a Contact.. etc., open this record in CRM and clear or change it’s email address.

Do this until the script returns only one result.

NOTE: Run also the script on ALL your organization databases (XXX_MSCRM, YYYY_MSCRM, AAAA_MSCRM, etc……)

These two steps are the most important, I’ll probably add other latter on.

Kind regards

Benjamin LECOQ

Posted by benlec | 1 Comments

CRM 4.0 E-Mail Connector Logger Tool

Hi all,

 

I’ve just made this tool to easily enable logging for the E-Mail Connector in CRM 4.0

The logging for the connector can be enabled by modifying the configuration file for the service like explained in this article:

 

http://blogs.msdn.com/benlec/archive/2008/03/25/how-to-implement-logging-for-the-microsoft-crm-4-0-e-mail-connector.aspx

 

The tool looks like this:

 

CRM 4.0 E-Mail Connector Logger GUI

 

It’s based on XPath to read and modify the Config File.

 

Here is how it works:

1°) Execute the tool on the E-Mail Connector box, it will detect and read the config file.

2°) The drop down list you see shows you the Deployment you have configured, you need to select one of these.

3°) Once the deployment is selected, it will retrieve the different profiles you configured (Incoming Users & Queues, Forward Mailbox and Outgoing profile)

4°) You can select the section you want to activate logging for. If you need to only activate logging for Incoming E-Mail on Peter Chimaera, then select the 1st Checkbox only and select Peter from the Drop down.

5°) Choose a FileName (there will be a default filename proposed) and a LogLevel.

6°) Click [Enable Logging]

 

Important Notes:

- Don’t close the tool once you enabled logging. It will STOP the logging. (it has some dialog box which reminds you the usage anyways)

- One you are done with your tests, click [Stop Logging]

- The log files will be placed in the SAME folder as the Microsoft.Crm.Tool.EmailAgent.xml file

- There will be no update of the Configuration during the test (if in the meantime a new user is configured, it will not take it in consideration) because once you click [Enable Logging] the tool will set the ConfigUpdatePeriod to ZERO to prevent any unexpected update during the test (to prevent cancelling logging).

 

Risks:

- There should be no risks to do this because the tool automatically Create a backup of the EmailAgentXML when we attempt to Enable Logging.

If an unexpected error occurs, the backup will be restored. The backup is restored also if you exit the application….

- You can run it if the EmailAgentXML has already been modified because it will check if the LogLevel and LogFile tag exists already or not and will either modify or create the tags accordingly.


Regards

Benjamin

CrmDiagTool4 for Microsoft CRM 4.0 update [4.0.7333.3]

Hi all,

 

Just a minor update here. (see download page)

 

I've added:

 

- Hotfix Information from Registry Information

 

----------------CRM Hotfix Installed----------------

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\1[BuildDate]: 5/27/2008 12:00:00 AM

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\1[FileName]: Microsoft.Crm.Application.Components.Sdk.FormControls.dll

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\1[Location]: c:\Program Files\Microsoft Dynamics CRM\wwwroot\bin

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\1[Version]: 4.0.7333.1041

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\2[BuildDate]: 5/27/2008 12:00:00 AM

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\2[FileName]: Microsoft.Crm.Application.Components.Sdk.FormControls.dll

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\2[Location]: c:\Program Files\Microsoft Dynamics CRM\wwwroot\help\bin

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\2[Version]: 4.0.7333.1041

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\3[BuildDate]: 5/27/2008 12:00:00 AM

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\3[FileName]: Microsoft.Crm.Application.Components.Core.dll

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\3[Location]: c:\Program Files\Microsoft Dynamics CRM\wwwroot\bin

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\3[Version]: 4.0.7333.1041

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\4[BuildDate]: 5/27/2008 12:00:00 AM

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\4[FileName]: Microsoft.Crm.Application.Components.Core.dll

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\4[Location]: c:\Program Files\Microsoft Dynamics CRM\wwwroot\help\bin

HKLM\Software\Microsoft\Updates\Microsoft Dynamics CRM Server\SP0\KB951319_Server\FileList\4[Version]: 4.0.7333.1041

 

 

- IFD Settings Information from DeploymentProperties Table (MSCRM_CONFIG)

 

----------------SQL: [IFD] DeploymentProperties SQL Table Information [MSCRM_CONFIG]----------------

[ADRootDomainScheme...............]: http

[ADSdkRootDomain..................]: L2003VPC:5555

[ADWebApplicationRootDomain.......]: L2003VPC:5555

[AppUseInProcessSdk...............]:

Etc.....

[AsyncJobOrgDatabaseMaintenanceInterval]:

 [PagingLimit......................]:

[ShowAuthenticationErrors.........]:

[SqlCommandTimeout................]:

Etc...

[SqlGovernorPerfDataPollingDuration]:

[SQMEnabled.......................]:

[TraceCallStack...................]:

[TraceCategories..................]: *:Error

[TraceDirectory...................]: c:\crmdrop\logs

[TraceEnabled.....................]:

[TraceFileSize....................]:

 

Cheers

Benjamin LECOQ

Posted by benlec | 1 Comments
Filed under: ,

Troubleshooting CRM E-Mail Issues in Microsoft CRM 4.0

Hi all,

 

After my post about the CRM Router Logging, I wanted to give you some examples about how to use CRM Platform trace and Router Logging to troubleshoot and fix pretty much all CRM E-Mail Issues.

 

- To see how enabling platform trace, please check this article or use CrmDiagTool4:

- To see how to enable Router Logging, please check this article:

 

(NOTE: you may need to copy the content of this article and paste it in WORD or Outlook to see the carriage return correctly, the Platform traces might be hard to read here like this.) 

 

Here are some concrete examples of analysis.

 

Symptom : Incoming E-Mails for CRM Users do not appear in CRM Application. (Incoming E-mails are not tracked in CRM)

 

EXAMPLE #1 :

 

I’ve sent an Email from External network to one of my CRM User. The email subject is “unknown mail”. You just need now to track this subject in the different log files.

 

CRM E-Mail Router LogFile:

 

05/05/2008 10:54:52 : #20669 - Checking for e-mail messages to process in mailbox Administrator@Titan.co.uk.

05/05/2008 10:54:52 : #49073 - Validating the e-mail message with subject "unknown mail" from "externaluser" <externaluser@Titan.co.uk> to "Administrator" <Administrator@Titan.co.uk> for delivery to Administrator@Titan.co.uk.

05/05/2008 10:54:52 : #1866 - Checking the e-mail message with subject "unknown mail" in mailbox Administrator@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers.

05/05/2008 10:54:52 : #60263 - The e-mail message with subject "unknown mail" in mailbox Administrator@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers was rejected.

05/05/2008 10:54:52 : #20669 - Checking for e-mail messages to process in mailbox Administrator@Titan.co.uk.

05/05/2008 10:54:52 : #53362 - There are no more e-mail messages to process in mailbox Administrator@Titan.co.uk.

05/05/2008 10:54:52 : #19780 - Closing mailbox Administrator@Titan.co.uk.

 

CRM Platform trace:

 

SOAP Xml:

<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Header>

<CrmAuthenticationToken xmlns="http://schemas.microsoft.com/crm/2007/WebServices">

<AuthenticationType xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">0</AuthenticationType>

<OrganizationName xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">TrevorsBangers</OrganizationName>

<CallerId xmlns="http://schemas.microsoft.com/crm/2007/CoreTypes">00000000-0000-0000-0000-000000000000</CallerId>

</CrmAuthenticationToken>

</soap:Header>

<soap:Body>

<Execute xmlns="http://schemas.microsoft.com/crm/2007/WebServices">

<Request xsi:type="CheckIncomingEmailRequest">

<MessageId>&lt;C7A125AC9281B74DA34740FDFC303F929E81@l2003vpc.Titan.co.uk&gt;</MessageId>

<Subject>unknown mail</Subject>

<From>"externaluser" &lt;externaluser@Titan.co.uk&gt;</From>

<To>"Administrator" &lt;Administrator@Titan.co.uk&gt;</To>

<Cc />

<Bcc />

</Request>

</Execute>

</soap:Body>

</soap:Envelope>

 

>Email delivery found a user or queue recipient who accepts e-mails based on correlation to an existing record (subject: unknown mail).

 

[2008-05-05 10:54:52.5] Process: w3wp |Organization:fddac4a2-c99e-422e-a859-5437eecc8cd4 |Thread:    7 |Category: Platform |User: 07e7e59a-caf9-4d20-874c-d33df1488fed |Level: Verbose | TrackingManager.GetTrackingData

                at TrackingManager.GetTrackingData(String subject, String[] emailAddresses, TrackingOptions trackingOptions)

                at EmailService.CheckIncoming(String messageId, String subject, String from, String to, String cc, String bcc, ExecutionContext context, Int32& reasonCode)

                at RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)

                at RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)

 

>Email tracking did not find a match or full matching was not requested (subject: unknown mail).

 

>Email delivery found no recipient user or queue who accepts this e-mail and the e-mail will be rejected (subject: unknown mail).

 

Here you see the E-Mail has been rejected (will not be tracked in CRM).

The CRM platform trace shows us the cause of this error, the latest thing we’ve checked here before raising the error is the Tracking Token of the E-Mail (TrackingManager.GetTrackingData()).

It seems like the tracking token is the problem here.

 

Now let’s have a look at the User’s Personal Options in CRM.

Here is how it’s set (default settings):

 

CRM E-Mail Personal Option 

 

The option is set to only accept E-Mail which are already part of an existing CRM conversation. In my test I only sent from external a simple regular mail (no-CRM), this is why It has been rejected.

We shall set any of the two other option to address the issue.

 

EXAMPLE #2 :

 

I’ve sent an Email from External network to one of my CRM User. The email subject is “unknown sender”. You just need now to track this subject in the different log files.

 

The Router log is the same as in EXAMPLE #1, all we need is the platform trace.

 

CRM Platform trace:

 

>Email delivery found a user or queue recipient who accepts e-mails based on whether the sender is an account / contact / etc. (subject: Unknown Sender).

 

>select contact0.ContactId as 'contactid', contact0.StateCode as 'statecode', contact0.EMailAddress1 as 'emailaddress1', contact0.EMailAddress2 as 'emailaddress2', contact0.EMailAddress3 as 'emailaddress3' from Contact as contact0 where ((contact0.DeletionStateCode in (0)) and ((((contact0.EMailAddress1 in ('externaluser@Titan.co.uk')) or (contact0.EMailAddress2 in ('externaluser@Titan.co.uk')) or (contact0.EMailAddress3 in ('externaluser@Titan.co.uk'))))))

[2008-05-05 11:08:56.4] Process: w3wp |Organization:fddac4a2-c99e-422e-a859-5437eecc8cd4 |Thread:    1 |Category: Platform.Sql |User: 07e7e59a-caf9-4d20-874c-d33df1488fed |Level: Info | CrmDbConnection.InternalExecuteReader

                at CrmDbConnection.InternalExecuteReader(IDbCommand command)

                at CrmDbConnection.ExecuteReader(IDbCommand command, Boolean impersonate)

                at CrmDbConnection.ExecuteReader(IDbCommand command)

                at BusinessProcessObject.ExecuteQuery(CrmDbConnection dbConnection, IDbCommand command, ISqlExecutionContext context)

                at BusinessProcessObject.DoRetrieveMultiple(BusinessEntityCollection entities, EntityExpression entityExp, ExecutionContext context)

                at BusinessProcessObject.RetrieveMultiple(EntityExpression entityExpression, ExecutionContext context)

                at AddressManager.ResolveToRecordType(AddressEntry[] addressEntries, ResolutionOptions resolutionOptions)

                at AddressManager.ResolveToContacts(AddressEntry[] addressEntries)

                at AddressManager.ResolveToExternalEntities(AddressEntry[] addressEntries)

                at EmailService.CheckIncoming(String messageId, String subject, String from, String to, String cc, String bcc, ExecutionContext context, Int32& reasonCode)

 

>select account0.AccountId as 'accountid', account0.StateCode as 'statecode', account0.EMailAddress1 as 'emailaddress1', account0.EMailAddress2 as 'emailaddress2', account0.EMailAddress3 as 'emailaddress3' from Account as account0 where ((account0.DeletionStateCode in (0)) and ((((account0.EMailAddress1 in ('externaluser@Titan.co.uk')) or (account0.EMailAddress2 in ('externaluser@Titan.co.uk')) or (account0.EMailAddress3 in ('externaluser@Titan.co.uk'))))))

[2008-05-05 11:08:56.4] Process: w3wp |Organization:fddac4a2-c99e-422e-a859-5437eecc8cd4 |Thread:    1 |Category: Platform.Sql |User: 07e7e59a-caf9-4d20-874c-d33df1488fed |Level: Info | CrmDbConnection.InternalExecuteReader

                at CrmDbConnection.InternalExecuteReader(IDbCommand command)

                at CrmDbConnection.ExecuteReader(IDbCommand command, Boolean impersonate)

                at CrmDbConnection.ExecuteReader(IDbCommand command)

                at BusinessProcessObject.ExecuteQuery(CrmDbConnection dbConnection, IDbCommand command, ISqlExecutionContext context)

                at BusinessProcessObject.DoRetrieveMultiple(BusinessEntityCollection entities, EntityExpression entityExp, ExecutionContext context)

                at BusinessProcessObject.RetrieveMultiple(EntityExpression entityExpression, ExecutionContext context)

                at AddressManager.ResolveToRecordType(AddressEntry[] addressEntries, ResolutionOptions resolutionOptions)

                at AddressManager.ResolveToAccounts(AddressEntry[] addressEntries)

                at AddressManager.ResolveToExternalEntities(AddressEntry[] addressEntries)

                at EmailService.CheckIncoming(String messageId, String subject, String from, String to, String cc, String bcc, ExecutionContext context, Int32& reasonCode)

 

etc..

 

>Email delivery found no recipient user or queue who accepts this e-mail and the e-mail will be rejected (subject: Unknown Sender).

 

We see here before raising the error we are trying to see if the E-Mail address of the sender ('externaluser@Titan.co.uk') Is registered to be used by an existing Account, Contact or Lead in CRM.

Then we reject the E-Mail.

 

If we have a look at the user E-Mail options (see EX#1) we see the option is set to Track only “E-mail messages from CRM Leads, Contacts and Accounts”.

This is not the case here as Externaluser is unknown, so we reject the E-Mail.

 

Symptom : Incoming E-Mails do not appear in CRM Queue (E-Mails are moved to undeliverable folder of the Queue Inbox).

 

EXAMPLE #1 :

 

I’ve sent an Email from External network to one of my CRM Queue. The email subject is “IncomingMailToQueueEx3”. You just need now to track this subject in the different log files.

 

CRM E-Mail Router LogFile:

 

05/05/2008 11:53:38 : #20669 - Checking for e-mail messages to process in mailbox crmqueue@Titan.co.uk.

05/05/2008 11:53:38 : #49073 - Validating the e-mail message with subject "IncomingMailToQueueEx3" from "externaluser" <externaluser@Titan.co.uk> to "crmqueue" <crmqueue@Titan.co.uk> for delivery to crmqueue@Titan.co.uk.

05/05/2008 11:53:38 : #1866 - Checking the e-mail message with subject "IncomingMailToQueueEx3" in mailbox crmqueue@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers.

05/05/2008 11:53:38 : #9466 - Accepting the e-mail message with subject "IncomingMailToQueueEx3" in mailbox crmqueue@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers.

05/05/2008 11:53:38 : #46519 - Delivering the e-mail message with subject "IncomingMailToQueueEx3" in mailbox crmqueue@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers.

05/05/2008 11:53:39 : #9628 - An error occurred while delivering the e-mail message with subject "IncomingMailToQueueEx3" in mailbox crmqueue@Titan.co.uk for delivery to http://l2003vpc:5555/TrevorsBangers. System.Web.Services.Protocols.SoapException: Server was unable to process request.

   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)

   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)

   at Microsoft.Crm.Sdk.Proxy.CrmService.Execute(Request Request)

   at Microsoft.Crm.Tools.Email.Providers.CrmPollingMailboxProvider.DeliverMessageInternal(EmailMessage emailMessage)

   at Microsoft.Crm.Tools.Email.Providers.ExchangePollingMailboxProvider.DeliverMessageInternal(EmailMessage emailMessage)

   at Microsoft.Crm.Tools.Email.Providers.CrmPollingMailboxProvider.DeliverMessage(EmailMessage emailMessage)

   at Microsoft.Crm.Tools.Email.Providers.CrmPollingMailboxProvider.Run()\r\n

  0x80040b05

  At least one system user or queue in the organization must be a recipient

  Platform

  At least one system user or queue in the organization must be a recipient

   at Microsoft.Crm.ObjectModel.EmailService.Deliver(Boolean userPromote, Guid emailId, String messageId, String subject, String from, String to, String cc, String bcc, DateTime receivedOn, String submittedBy, String importance, String body, BusinessEntityCollection attachments, Guid campaignResponseId, ExecutionContext context)

   at Microsoft.Crm.ObjectModel.EmailService.DeliverIncoming(String messageId, String subject, String from, String to, String cc, String bcc, DateTime receivedOn, String submittedBy, String importance, String body, BusinessEntityCollection attachments, ExecutionContext context)

InnerException Type:Microsoft.Crm.CrmException

05/05/2008 11:53:39 : #30463 - Moving the e-mail message with subject "IncomingMailToQueueEx3" in mailbox crmqueue@Titan.co.uk to the undeliverable folder because it has been marked as undeliverable.

 

CRM Platform trace:

 

>select queue0.QueueId as 'queueid', queue0.EMailAddress as 'emailaddress', queue0.PrimaryUserId as 'primaryuserid', queue0.IncomingEmailFilteringMethod as 'incomingemailfilteringmethod', queue0.PrimaryUserIdDsc as 'primaryuseriddsc', queue0.PrimaryUserIdYomiName as 'primaryuseridyominame', queue0.PrimaryUserIdName as 'primaryuseridname' from Queue as queue0 where ((queue0.DeletionStateCode in (0)) and ((((queue0.EMailAddress in ('crmqueue@Titan.co.uk'))))))

[2008-05-05 11:53:38.8] Process: w3wp |Organization:fddac4a2-c99e-422e-a859-5437eecc8cd4 |Thread:    7 |Category: Exception |User: 07e7e59a-caf9-4d20-874c-d33df1488fed |Level: Error | CrmException..ctor

                at CrmException..ctor(String message, Exception innerException, Int32 errorCode, Boolean isFlowControlException, Boolean enableTrace)

                at CrmException..ctor(String message, Exception innerException, Int32 errorCode, Boolean isFlowControlException)

                at CrmException..ctor(String message, Int32 errorCode)

                at CrmSecurityException..ctor(String message, Int32 errorCode)

                at SecurityLibrary.TryCheckPrivilege(Guid user, Guid privilege, ExecutionContext context)

                at SecurityLibrary.CheckPrivilege(Guid user, Guid privilege, ExecutionContext context)

                at AddressManager.GetOwnerCandidate(AddressEntry addressEntry, BusinessEntity businessEntity)

                at AddressManager.ResolveToRecordType(AddressEntry[] addressEntries, ResolutionOptions resolutionOptions)

                at AddressManager.ResolveToQueues(AddressEntry[] addressEntries)

                at AddressManager.ResolveToInternalEntities(AddressEntry[] addressEntries)

                at EmailService.CheckIncoming(String messageId, String subject, String from, String to, String cc, String bcc, ExecutionContext context, Int32& reasonCode)

 

>Crm Exception: Message: SecLib::CheckPrivilege failed. Returned hr = -2147209463, User: 20d00467-34c4-dc11-84c0-0003ff1854c9, ErrorCode: -2147209463

 

The UserId mentioned here appears to be the Owner of the Queue (if you look it up in the SystemUserBase).

The Error code here is: -2147209463 = HR 0x80042F09

 

Error 80042F09 means “The user has not been granted any licenses or the user has not been assigned any roles.

 

We had a look in the Queue properties and indeed the Owner didn’t have any role, we need to add a role to the Queue owner to address this.

 

Here you are, I may add more examples in the future I you are interested.


Hope this helps

 

Benjamin

Outlook Inbox folders stuck on Loading message in CRM 4.0

Hi all,

 

Do you get this with CRM 4.0 Client?

 

 Loading

  

We are seeing many request of this kind in CRM Support.

 

THE IS A FIX AVAILABLE FOR DOWNLOAD, PLEASE CLICK HERE TO GET IT:

KB952724 E-mail messages are not displayed in the folders in the Microsoft Dynamics CRM 4.0 On-Premise client for Outlook

 

Our team is working to fix it, an hotfix will be available but we can’t tell when right now.

 

To make it simple, the cause of this issue is a timing issue between Outlook/.Net/CrmAddin.

If you do the following you can workaround the issue.

 

-          Open Outlook, disable CrmAddin

-          Close Outlook, Open Outlook, Enable CrmAddin.

-           Issue is gone ! simply because we waited a bit to load our Addin after Outlook startup.

 

So after having a closer look, I guess the workaround above is not really easy to do and quite annoying, so for now you can try this:

 

-          You can enable the Security on Addins in Outlook so that you get prompted to Load the CrmAddin on Outlook startup.

Behind the scene, the prompt will delay the loading of the CrmAddin and make the issue disappear.

 

-          For OL2007, go to Tools, Trusted Center and check “Apply macro security settings to installed add-ins”. Restart Outlook.

When you now start Outlook, you will get prompted to load the addin with this:

 

 

Trust CrmAddin

 

 

-          Simply Click “Enable application add-in” and it should work.

DON’T select “Trust all documents” because you’ll not be prompted anymore and this is not what we want.

 

I hope this will help you to workaround this while we are working on release a proper fix.


Any comments are welcome, if you want to propose other workarounds waiting for the fix :-) 

 

Regards

Benjamin LECOQ

 

Posted by benlec | 14 Comments
Filed under:

How to implement Logging for the Microsoft CRM 4.0 E-mail Connector

Hi all,

 

Here you’ll not get a tool for once but instructions and demo about how to implement tracing for our Microsoft CRM 4.0 E-Mail connector.

In CRM 3.0 we were using Registry Keys to do this but there was not a lot of granularity, we could only trace or not the whole service activity.

Here you will see we can now use regular event log or custom log file, we can set different level of tracing AND we can set the tracing separately for each E-Mail Provider (Like tracing Pop3, tracing SMTP out, tracing SMTP In, etc…..)

 

To do this you simply need now to modify the XML Configuration file of the Microsoft CRM 4.0 E-Mail Connector.

For the whole explanation and a demo, have a look at the video bellow:

CLICK Here for Full-Screen

 

Here is what you need to remember from the presentation :

 

<LogLevel>

Description

-1

Use default settings.(Inherits from <SystemConfiguration> node)

0

None.

1

Normal (typically errors only).

2

Medium (advanced processing information down to the mailbox level).

3

High (advanced processing information down to the message level).

 

 

<LogFile>

Description

C:\MyLog.txt

If you specify this tag, logging information will be written into a Log file you specify. (Ex: <LogFile>C:\MyLog.txt</LogFile>)

Tag Does Not Exist

If you don’t add this tag, the event will be recorded into the regular Windows Appplication Log.(Source: « MSCRMEmail »)

 

 

<ConfigUpdatePeriod>

This tag has to be set to ZERO while you are debugging (while you are activation the logging)

 

In Addition, here are some precisions about the different sections of the XML configuration file.

If you need to troubleshoot INCOMING Email issue, you need to set the Logging here:

 

Incoming Email Issue 

 

The providerClass is ExchangePollingMailboxProvider (or Pop3PollingMailboxProvider) there is ONE node of this kind for every User or Queue you have in CRM.

There is probably many of these in your file. you need to add the Logging here for your specific user you are troubleshooting.

 

For OUTGOING Email issues, you need to add the Logging here:

 

Send Email Issues

 

The provider has to be SmtpPollingSendEmailProvider. There will be only ONE section of this kind by deployment. It will be shared with ALL the CRM Users and Queues. So if you had logging at this level, you'll have the information for ALL Users.

 

Htp

 

Benjamin LECOQ

CrmDiagTool4 for Microsoft CRM 4.0 has been released [4.0.7333.2]

Hi all,

 

I’ve made the CrmDiagTool for CRM 4.0

It’s been a while since I wanted to post this, but I wanted to wait and see if the tool was working fine.

Now that we have tested it during some weeks already, it’s ready to be available on my blog site.

 

The major difference between v3 and v4 is the tool does not work on the client side.

The reason is because we ship a very similar version of the tool already with CRM Client software (called Diagnostic Wizard)

 

So, what does the tool in v4?

 

ü  Microsoft CRM Server

ü  Enable/Disable Platform tracing, Zip the trace folder for you if needed.

ü  Enable/Disable DevErrors

ü  Generate Machine Report

NB: These 3 actions are now separated clearly, the Platform Tracing and DevErrors facilities shows now the current status of the option dynamically.

 

ü  Microsoft SRS Data Connector

ü  Generate Machine Report

 

ü  Microsoft CRM E-Mail Router

ü  Generate Machine Report

ü  (Next version will add tracing for the Email service as well.)

 

What the tool looks like?

 

CrmDiagTool4 Main UI 

 

How to run it?

 

Well unzip the archive on the target server (CRM Server or Router or SRS for CRM).

Double click on the Exe file and select the appropriate target from the drop down list.

 

NOTE: This tool does not work remotely, it has to be executed locally on the Target server!

 

Details about the reports:

 

          CRM Server Report

        System Information

        Environment Variables

        TCPIP Parameters Registry

        Boot.ini Content

        .Net Framework Registration

        CRM Services Status and Logon Info

        CRM Registry Keys

        CRM Installed Files

          %ProgramFiles%

          GAC

        Web Sites Bindings

        ApplPool Indentities

        CRM WebSite Authentication

        SQL Server Information

        CRM System Settings

        CRM AD Groups Information

        Organization and Deployment Informations

(retrieve by SDK or SQL queries)

 

          SRS Data Connector Report

        System Information

        Environment Variables

        SRS Data Connector Installed  files

          %ProgramFiles%\CRM Data Conn

          %ProgramFiles%\ReportServer

        ReportServer Settings (WMI)

        Report Manager Settings (WMI)

        RSReportServer.config content

        RSSrvPolicy.config content

        SRSDataConnectorSetup.log

 

          CRM E-Mail Router Report

        System Information

        Environment Variables

        CRM E-Mail Router  nstalled  files

        CRM E-Mail Router Service Info

        Microsoft.Crm.Tools.EmailAgent.Xml content

        Crm40ExchangeSetup.log

 

Where to download it?

 

Go to the Download Page on the left menu of this blog or click here for a direct download.

  

Hope you will like it, I spent quite some time on that J

 

Regards

Benjamin LECOQ

 

Posted by benlec | 19 Comments
Filed under: ,
More Posts Next page »
 
Page view tracker