Dynamics 365 – Habilite/Desabilite Plugins e Workflows Programaticamente


Olá pessoal,

Como muitos de nós já sabemos, plugins e workflows oneram um precioso tempo do CRM para serem processados. Devido a isso, por muitas vezes precisamos que eles sejam desabilitados antes de iniciarmos uma integração ou migração no CRM, certo?!

Assim, criei um console application que podemos executar todas as vezes em que desejarmos habilitar ou desabilitar nossos plugins e workflows. Minha ideia foi de criar um código exemplo para que seja utilizado da melhor forma por cada caso.

Um exemplo de uso seria criar dois serviços agendados no agendador de tarefas do Windows (Windows Task Schedule). Assim um deles desabilitariam e outro habilitariam os plugins e workflows em determinado período.

Bom vamos ao código. Primeiro a Console Application:

using System;
using System.Linq;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Crm.Sdk.Messages;

namespace ManagePluginsWorkflows
{
    class Program
    {
        static void Main(string[] args)
        {
            // *** Define if Plugins / Workflows will be ENABLED or DISABLED ***
            bool deactivate = true;

            // Get CRM Connection
            IOrganizationService orgService = new CrmConnection().GetConnection();

            // Get Organization Service (working with Lambda)
            OrganizationServiceContext context = new OrganizationServiceContext(orgService);

            // Manage Plugin's Status
            ManagePlugins(context, deactivate);

            // Manage Workflow's Status
            ManageWorkflows(context, deactivate);

            Console.ReadKey();
        }

        private static void ManagePlugins(OrganizationServiceContext context, bool deactivate)
        {
            int pluginStateCode = (deactivate ? 1 : 0); // 1 = DISABLED, 0 = ENABLED
            int pluginStatusCode = (deactivate ? 2 : 1); //  2 = DISABLED, 1 = ENABLED

            Console.WriteLine(string.Concat((deactivate ? "Deactivating" : "Activating"), " Plugins"));
            Console.WriteLine();

            // Retrieve Plugins records
            var plugins = (from m in context.CreateQuery("sdkmessageprocessingstep")
                           where m.GetAttributeValue<BooleanManagedProperty>("ishidden").Value == false // Only non internal plugins (CRM Core)
                           // If you want some specific(s) plugin(s) add here a WHERE clause!
                           select m);

            // Loop results
            foreach (var plugin in plugins)
            {
                // Get Current State Code
                int stateCode = ((OptionSetValue)plugin["statecode"]).Value;

                // Get the Name of State Code
                string stateValueName = GetPluginStateName(stateCode);

                // Check if plugin is already in the Status wanted
                if (stateCode != pluginStateCode)
                {
                    Console.Write(string.Concat("Plugin Name: ", plugin["name"], " Current Status: ", stateValueName));

                    // Set wanted State and Status code
                    plugin["statecode"] = new OptionSetValue(pluginStateCode);
                    plugin["statuscode"] = new OptionSetValue(pluginStatusCode);

                    // Update current Plugin
                    context.UpdateObject(plugin);
                    context.SaveChanges();

                    Console.Write(string.Concat(" *** Status has been Changed: ", GetPluginStateName(pluginStateCode), " ***"));
                    Console.WriteLine();
                }
                // if plugin is already set to wanted Status
                else
                {
                    Console.WriteLine(string.Concat("Plugin Name: ", plugin["name"], " Current Status is already: ", stateValueName));
                }
            }

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(string.Concat("All Plugins have been set to ", (deactivate ? "DISABLED" : "ENABLED")));
            Console.WriteLine();
            Console.WriteLine();
        }

        private static void ManageWorkflows(OrganizationServiceContext context, bool deactivate)
        {
            int workflowStateCode = (deactivate ? 0 : 1); // 0 = DISABLED, 1 = ENABLED
            int workflowStatusCode = (deactivate ? 1 : 2); // 1 = DISABLED, 2 = ENABLED 

            Console.WriteLine(string.Concat((deactivate ? "Deactivating" : "Activating"), " Workflows"));
            Console.WriteLine();

            // Retrieve Workflow records
            var workflows = (from m in context.CreateQuery("workflow")
                             where m.GetAttributeValue<int>("type") == 1 // Only Workflows in "Definition" (1) Type
                             where m.GetAttributeValue<int>("category") == 0 // Only Workflows
                             // If you want some specific(s) workflow(s) add here a WHERE clause!
                           select m);

            // Loop results
            foreach (var workflow in workflows)
            {
                // Get Current State Code
                int stateCode = ((OptionSetValue)workflow["statecode"]).Value;

                // Get the Name of State Code
                string stateValueName = GetWorkflowStateName(stateCode);

                // Check if Workflow is already in the Status wanted
                if (stateCode != workflowStateCode)
                {
                    Console.Write(string.Concat("Workflow Name: ", workflow["name"], " Current Status: ", stateValueName));

                    SetStateRequest setStateRequest = new SetStateRequest
                    {
                        EntityMoniker = workflow.ToEntityReference(),
                        State = new OptionSetValue(workflowStateCode),
                        Status = new OptionSetValue(workflowStatusCode)
                    };
                    
                    // Update Wrokflow Status
                    context.Execute(setStateRequest);

                    Console.Write(string.Concat(" *** Status has been Changed: ", GetWorkflowStateName(workflowStateCode), " ***"));
                    Console.WriteLine();
                }
                // if Workflow is already set to wanted Status
                else
                {
                    Console.WriteLine(string.Concat("Workflow Name: ", workflow["name"], " Current Status is already: ", stateValueName));
                }
            }

            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(string.Concat("All Workflows have been set to ", (deactivate ? "DISABLED" : "ENABLED")));
            Console.WriteLine();
            Console.WriteLine();
        }

        private static string GetPluginStateName(int value)
        {
            if (value == 0)
            {
                return "Enabled";
            }
            else
            {
                return "Disabled";
            }
        }

        private static string GetWorkflowStateName(int value)
        {
            if (value == 1)
            {
                return "Enabled";
            }
            else
            {
                return "Disabled";
            }
        }
    }
}

O código não tem muito segredo, basicamente criei dois métodos um para cada processo (plugin e workflow). Dentro dos método faço um select no registros e depois habilito/desabilito de acordo com a variável “deactivate“. O resto é só história… rs

A principal parte que deve ser lembrada é a definição da variável “deactivate“:

bool deactivate = true;

Que desejamos desabilitar todos os plugins e workflows. Use o valor “TRUE“. Se queremos habilitar use o valor “FALSE“.

Agora a classe CrmConnection:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Configuration;

namespace ManagePluginsWorkflows
{
    public class CrmConnection
    {
        IOrganizationService _orgService = null;

        public IOrganizationService GetConnection()
        {
            return GetConn(null);
        }

        #region Private Methods

        private IOrganizationService GetConn(string connectionString)
        {
            if (_orgService == null)
            {
                // Obtain connection configuration information for the Microsoft Dynamics
                // CRM organization web service.
                connectionString = GetServiceConfiguration();

                if (connectionString != null)
                {
                    // Connect to the CRM web service using a connection string.
                    CrmServiceClient conn = new CrmServiceClient(connectionString);

                    // Cast the proxy client to the IOrganizationService interface.
                    if (conn.OrganizationWebProxyClient != null)
                    {
                        _orgService = conn.OrganizationWebProxyClient;
                    }
                    else if (conn.OrganizationServiceProxy != null)
                    {
                        _orgService = conn.OrganizationServiceProxy;
                    }
                }
            }

            return _orgService;
        }

        /// 


<summary>
        /// Gets web service connection information from the app.config file.
        /// If there is more than one available, the user is prompted to select
        /// the desired connection configuration by name.
        /// </summary>



        /// <returns>A string containing web service connection configuration information.</returns>
        private static string GetServiceConfiguration()
        {
            // Get available connection strings from app.config.
            int count = ConfigurationManager.ConnectionStrings.Count;

            // Create a filter list of connection strings so that we have a list of valid
            // connection strings for Microsoft Dynamics CRM only.
            List<KeyValuePair<string, string>> filteredConnectionStrings =
                new List<KeyValuePair<string, string>>();

            for (int a = 0; a < count; a++)
            {
                if (isValidConnectionString(ConfigurationManager.ConnectionStrings[a].ConnectionString))
                    filteredConnectionStrings.Add
                        (new KeyValuePair<string, string>
                            (ConfigurationManager.ConnectionStrings[a].Name,
                            ConfigurationManager.ConnectionStrings[a].ConnectionString));
            }

            // No valid connections strings found. Write out and error message.
            if (filteredConnectionStrings.Count == 0)
            {
                Console.WriteLine("An app.config file containing at least one valid Microsoft Dynamics CRM " +
                    "connection string configuration must exist in the run-time folder.");
                Console.WriteLine("\nThere are several commented out example connection strings in " +
                    "the provided app.config file. Uncomment one of them and modify the string according " +
                    "to your Microsoft Dynamics CRM installation. Then re-run the sample.");
                return null;
            }

            return filteredConnectionStrings[0].Value;
        }

        /// 


<summary>
        /// Verifies if a connection string is valid for Microsoft Dynamics CRM.
        /// </summary>



        /// <returns>True for a valid string, otherwise False.</returns>
        private static Boolean isValidConnectionString(string connectionString)
        {
            // At a minimum, a connection string must contain one of these arguments.
            if (connectionString.Contains("Url=") ||
                connectionString.Contains("Server=") ||
                connectionString.Contains("ServiceUri="))
                return true;

            return false;
        }

        #endregion Private Methods
    }
}

Essa classe é a mesma que encontramos no SDK. Apenas para criarmos a conexão com o CRM!

Por fim, o arquivo Web.Config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <connectionStrings>
    <add name="Server=CRM Online, organization=ORG_NAME, user=USER_NAME" connectionString="Url=URL; Username=USER_NAME; Password=PASSWORD; authtype=Office365" />
  </connectionStrings>
</configuration>

Definimos a “connection string” que nosso CRM possui!

 

Pronto! É isso!

[]’s,

Tiago

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.