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

Anúncios

Sobre Tiago Michelini Cardoso

I have been working with IT since 2006, almost of this time using Microsoft Dynamics CRM/365 as a source of solutions. I graduated in Bachelor of Information Systems at FIAP (Brazil) in 2012. I really love what I do! Technology has been my interest since always. Even in a tool different world of the current. When we didn't have internet, tablets, smartphones e social networks! Although I have worked in some roles, I can't give up "the developer life". Even so far of the greatest developers. Development in general is the thing that I love to work! I started my contributions about Dynamics in 2010. At the beginning, I used to help at MSDN and TechNet forums. But now, I'm dedicating all my time in my personal blog! Currently, I have the enormous honour of being the only Brazilian who got the award for Microsoft MVP (Most Valuable Professional) for Microsoft Dynamics CRM/365 product. I have been receiving the award since 2012.
Esse post foi publicado em Dynamics 365, Dynamics CRM e marcado , , , , , , , . Guardar link permanente.

Deixe um comentário

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

Logotipo do WordPress.com

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

Imagem do Twitter

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

Foto do Facebook

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

Foto do Google+

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

Conectando a %s