CRM 2011 – Automatically Enable/Disable Plug-ins and Workflows

I have recently built a data migration tool for Microsoft Dynamics CRM 2011. Before the migration runs, it is important to deactivate all active workflow and plug-in steps so that we prevent our custom business logic from executing which could potentially slow down the migration process. Once the migration is complete, we can reactivate the workflow and plug-in steps so that the system functions as expected.

The first step is to obtain the ID of the current system user which can be done using the following code snippet. We will need this to assign workflows at a later stage.

private static Guid GetSystemUserId()
{
    Guid userId = Guid.Empty;
    string domainName = "mydomain\user";

    QueryExpression query = new QueryExpression { EntityName = "systemuser" };
    query.Criteria.AddCondition("domainname", ConditionOperator.Equal, domainName);

    EntityCollection results = _sdk.RetrieveMultiple(query);
    if (results.Entities.Count > 0)
    {
        userId = results[0].Id;
    }

    return userId;
}

Next, we need to retrieve all active workflow processes by querying the workflow entity. We only want to retrieve workflows where the statecode is “1” (active), the statuscode is “2” (published) and the type is “1” (definition).

private static List<Guid> GetActiveWorkflowIds()
{
    List<Guid> activatedWorkflowIds = new List<Guid>();

    QueryExpression query = new QueryExpression { EntityName = "workflow" }; 
    query.Criteria.AddCondition("statecode", ConditionOperator.Equal, 1);   
    query.Criteria.AddCondition("statuscode", ConditionOperator.Equal, 2);
    query.Criteria.AddCondition("type", ConditionOperator.Equal, 1);

    EntityCollection results = _sdk.RetrieveMultiple(query);
    activatedWorkflowIds = results.Entities.ToList().Select(e => e.Id).ToList();

    return activatedWorkflowIds;
}

We also need all active plug-in steps by querying the sdkmessageprocessingstep entity. It is important to filter on plug-ins that we have developed ourselves so that we don’t retrieve any of the built-in platform plug-in steps.

private static List<Guid> GetPluginIds()
{
    List<Guid> pluginIds = new List<Guid>();

    QueryExpression query = new QueryExpression { EntityName = "sdkmessageprocessingstep" };    
    query.Criteria.AddCondition("name", ConditionOperator.BeginsWith, "Frostys");  

    EntityCollection results = _sdk.RetrieveMultiple(query);
    pluginIds = results.Entities.ToList().Select(e => e.Id).ToList();

    return pluginIds;
}

Before we can change the status of workflows from active to inactive (or vice versa), we must first assign each of the workflows to ourselves, hence the need to obtain the systemuserid in the first step of the process.

private static void AssignWorkflows(Guid systemUserId)
{
    _workflowIds.ForEach(w =>
    {
        _sdk.Execute(new AssignRequest
        {
            Assignee = new EntityReference("systemuser", systemUserId),
            Target = new EntityReference("workflow", w)
        });
    });
}

The last step of the process is to change the status of the workflows and plug-in steps. This is done using the SetStateRequest. I have created a method called ToggleProcessState which takes in a boolean parameter to indicate whether we are disabling or enabling the plug-in and workflow steps.

private static void ToggleProcessState(bool disable)
{
    // workflow stateCode = 0 and statusCode = 1 (inactive), stateCode = 1 and statusCode = 2 (active)
    // plugin stateCode = 1 and statusCode = 2 (inactive), stateCode = 0 and statusCode = 1 (active)

    int wfStateCode = disable ? 0 : 1;
    int wfStatusCode = disable ? 1:  2;
    int pluginStateCode = disable ? 1 : 0;
    int pluginStatusCode = disable ? 2 : 1;

    // workflows
    _workflowIds.ForEach(w =>
    {
        _sdk.Execute(new SetStateRequest
        {
            EntityMoniker = new EntityReference("workflow", w),
            State = new OptionSetValue(wfStateCode),
            Status = new OptionSetValue(wfStatusCode)
        });
    });

    _pluginIds.ForEach(p =>
    {
        _sdk.Execute(new SetStateRequest
        {
            EntityMoniker = new EntityReference("sdkmessageprocessingstep", p),
            State = new OptionSetValue(pluginStateCode),
            Status = new OptionSetValue(pluginStatusCode)
        });
    });
}
Advertisements

5 thoughts on “CRM 2011 – Automatically Enable/Disable Plug-ins and Workflows”

  1. I have used “GetPluginIds()” function in my code my questions is that what is “_sdk” in this line _sdk.RetrieveMultiple(query); ? can you please explain it.

    Can I use this code in VS 2008?

    1. Hi

      The _sdk variable is of type IOrganizationService which contains the methods to interact with the CRM platform. You can run this code as long as you have .NET 4.0 or higher installed.

  2. Thanks for posting this solution.

    I want to enable/disable plugins in script component of SSIS Package. I have developed SSIS Packages in BIDS 2008 which is using .NET SDK 3.5 and I am using CRM 2011 which is using .Net SDK 4.0. I can’t use above code in my Script Component.

    One person has written utility class using .Net SDK 3.5 Below is the link of utility.

    http://blogs.msdn.com/b/apurvghai/archive/2012/06/06/ssis-2008-integration-with-crm-2011-on-premise.aspx?CommentPosted=true#comments

    In utility he has written a class like

    OrganizationRequest request = new OrganizationRequest();

    request.RequestName = “RetrieveAttribute”;
    request.Parameters = new ParameterCollection();
    request.Parameters.Add(new KeyValuePair(“EntityLogicalName”, “contact”));
    request.Parameters.Add(new KeyValuePair(“RetrieveAsIfPublished”, true));
    request.Parameters.Add(new KeyValuePair(“LogicalName”, “new_cardtype”));
    OrganizationResponse response = (OrganizationResponse)CrmHelper.OrgService.Execute(request);

    Can you please explain me how I can convert below code into OrganizationRequest object?

    _pluginIds.ForEach(p =>
    {
    _sdk.Execute(new SetStateRequest
    {
    EntityMoniker = new EntityReference(“sdkmessageprocessingstep”, p),
    State = new OptionSetValue(pluginStateCode),
    Status = new OptionSetValue(pluginStatusCode)
    });
    });

    Appreciate your help.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s