Разработка
30
Сен
0

Массовая активация/деактивация плагинов и Бизнес-процессов

Перед выполнением миграции данных часто бывает необходимо отключить всю серверную бизнес-логику (плагины и бизнес-процессы). Это может быть связано как с вопросами производительности, так другой логике формирования исходных данных. После завершения миграции необходимо повторно ее включить.

Чтобы не проделывать все это ручками напишем консольное приложение, которое провернет все это автоматически. Вот его код:

using System;
using System.Collections.Generic;
using System.Linq;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Crm.Sdk.Messages;

using System.ServiceModel;
using System.ServiceModel.Description;
using System.Runtime.Serialization;

namespace ToggleProcessState
{
    class Program
    {
        static void Main(string[] args)
        {
            // Подключаемся к CRM
            ClientCredentials credentials = new ClientCredentials();
            credentials.Windows.ClientCredential = new System.Net.NetworkCredential("Administrator", "1qaz@WSX", "D2012");
            Uri uri = new Uri("http://win-ebu0m4kvf06/superfirma/XRMServices/2011/Organization.svc");
            OrganizationServiceProxy proxy = new OrganizationServiceProxy(uri, null, credentials, null);
            proxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
            IOrganizationService service = (IOrganizationService)proxy;

            // Возвращаем пользователя, на которого будем назначать БП
            Console.WriteLine("Получаем пользователя."); 
            
            QueryExpression getUsers = new QueryExpression { EntityName = "systemuser" };
            getUsers.Criteria.AddCondition("domainname", ConditionOperator.Equal, "D2012\\Administrator");
            EntityCollection users = service.RetrieveMultiple(getUsers);

            Guid userId = Guid.Empty;
            if (users.Entities.Count > 0)
                userId = users[0].Id;
            else
                return; // Если никто не найден - прекращаем выполнение

            // Возвращаем активные шаги плагинов
            List<Guid> pluginIds = new List<Guid>();

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

            EntityCollection pluginsCollection = service.RetrieveMultiple(getPlugins);
            pluginIds = pluginsCollection.Entities.ToList().Select(e => e.Id).ToList();

            Console.WriteLine("Отобрано плагинов: " + pluginIds.Count);
            
            // Возвращаем активные Бизнес-процессы
            List<Guid> workflowIds = new List<Guid>();

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

            EntityCollection workflowsCollection = service.RetrieveMultiple(getWorkflows);
            workflowIds = workflowsCollection.Entities.ToList().Select(e => e.Id).ToList();

            Console.WriteLine("Отобрано Бизнес-процесов: " + workflowIds.Count);

            // Меняем Ответственного за Бизнес-процессы            
            Console.WriteLine("Меняем ответственного за Бизнес-процессы.");

            workflowIds.ForEach(w =>
            {
                service.Execute(new AssignRequest 
                {
                    Assignee = new EntityReference("systemuser", userId),
                    Target = new EntityReference("workflow", w)
                });
            });

            // Деактивируем все Бизнес-процессы и шаги плагинов
            Console.WriteLine("Отключаем все процессы.");
            ToggleProcessState(true, pluginIds, workflowIds, service);
            Console.WriteLine("Все процессы отключены");

            // Активируем все Бизнес-процессы и шаги плагинов
            //Console.WriteLine("Включаем все процессы.");
            //ToggleProcessState(false, pluginIds, workflowIds, service);
            //Console.WriteLine("Все процессы включены");

            Console.WriteLine("Press <Enter> to exit.");
            Console.ReadLine();
        }

        private static void ToggleProcessState(bool disable, List<Guid> pluginIds, List<Guid> workflowIds, IOrganizationService service)
        {
            // Плагины 
            // inactive: stateCode = 1, statusCode = 2
            // active: stateCode = 0, statusCode = 1

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

            pluginIds.ForEach(p =>
            {
                service.Execute(new SetStateRequest 
                {
                    EntityMoniker = new EntityReference("sdkmessageprocessingstep", p),
                    State = new OptionSetValue(pluginStateCode),
                    Status = new OptionSetValue(pluginStatusCode)
                });
            });
            
            // Бизнес-процессы
            // stateCode = 0, statusCode = 1
            // stateCode = 1, statusCode = 2
            
            int wfStateCode = disable ? 0 : 1;
            int wfStatusCode = disable ? 1:  2;
            
            workflowIds.ForEach(w =>
            {
                service.Execute(new SetStateRequest 
                {
                    EntityMoniker = new EntityReference("workflow", w),
                    State = new OptionSetValue(wfStateCode),
                    Status = new OptionSetValue(wfStatusCode)
                });
            });            
        }
    }
}

Что тут у нас происходит:

  • Подключаемся к CRM (ну, как обычно :));
  • Запрашиваем запись текущего Пользователя, на которого будем назначать Бизнес-процессы перед сменой их состояния, поскольку система не позволяет менять состояние «чужих» БП;
  • Возвращаем все активные шаги плагинов. При этом отсеиваем стандартные шаги плагинов (встроенные в платформу);
  • Возвращаем все активные БП и переназначаем их на текущего пользователя;
  • Вызываем функцию ToggleProcessState, в которую первым параметром передаем булево значение, в зависимости от того, хотим мы включить или отключить все процессы.


Комментарии (0)

*

code