【Dynamics CRM 2011】ワークフローやプラグインを動的に有効 / 無効化する

Dynamics CRMに登録されているワークフローやプラグインも、エンティティのレコードとして内部で保存されています。

どちらもStateCode / StatusCodeを所持しており、SDKAPIで有効 / 無効を切り替えることも可能です。

ワークフローはともかく、何らかのバッチ処理で大量のデータを処理したい場合はプラグインが有効になっているとどうしてもその分処理時間が長くなってしまうので、事前にどうでもいいプラグインを無効化するところまでバッチ化してしまうのも一つの手です。

対象のレコードを抽出する(SQL

エンティティなので普通にSQLでもとってこれます。まずはワークフロー。

SELECT
    *
FROM
    Workflow
WHERE
    [type] = 1

Workflow.type = 1で抽出することで、定義済みのワークフローのレコードを取得することが出来ます。

他のエンティティの例に漏れず、[Workflowid]と言うカラムにそのレコードのGUIDがあります。

流石に*で検索するとよくわからん、って場合はこの辺を見ておけばいいと思います。

SELECT
    name
    ,statecode
    ,statuscode
    ,workflowid
FROM
    Workflow
WHERE
    [type] = 1

ワークフローは「Statecode = 1 かつ Statuscode = 2」だとアクティブ、「Statecode = 0 かつ Statuscode = 1」だと非アクティブです。

どっちか片方取ってきたい場合は適当にWHEREに入れちゃいましょう。

次はプラグインです。「Sdkmessageprocessingstep」と言うやたら長い名前のエンティティに入っています。

SELECT
    *
FROM
    Sdkmessageprocessingstep
WHERE
    IsCustomizable = 1
    AND IsHidden = 0

WHEREなしで調べようとすると結構だるいです。(内部でのみ使われている何かが大量にヒットする)

もちろんこれも[Sdkmessageprocessingstepid]と言うカラムを持っています。

SELECT
    name
    ,eventhandlername
    ,sdkmessageidname
    ,statecode
    ,statuscode
    ,Sdkmessageprocessingstepid
FROM
    Sdkmessageprocessingstep
WHERE
    IsCustomizable = 1
    AND IsHidden = 0

こんな感じのクエリを投げればどれがどれだかなんとなーくつかめると思います。

プラグインのほうは「Statecode = 0 かつ Statuscode = 1」だとアクティブ、「Statecode = 1 かつ Statuscode = 2」だと非アクティブです。ワークフローとは逆ってことですね。

対象のレコードを抽出する(SDK

当たり前ですがSDKAPIで取得することも出来ます。改めて書く必要があるのか、って感じですが。

// Get Workflow
var w = new QueryExpression("workflow")
{
    ColumnSet = new ColumnSet("name", "statecode", "statuscode"),
};

w.Criteria.AddCondition("type", ConditionOperator.Equal, 1);

var workFlows = service.RetrieveMultiple(w).Entities
                    .Select(x => new
                        {
                            Id = x.Id,
                            Name = x.Attributes["name"] as string,
                            IsDisabled = ((int) x.Attributes["statecode"]) == 0
                                        && ((int) x.Attributes["statuscode"]) == 1,
                        }
                    );

// Get Plugin
var p = new QueryExpression("sdkmessageprocessingstep")
{
    ColumnSet = new ColumnSet("name", "eventhandlername", "sdkmessageidname", "statecode", "statuscode"),
};

p.Criteria.AddCondition("iscustomizable", ConditionOperator.Equal, 1);
p.Criteria.AddCondition("ishidden", ConditionOperator.Equal, 0);

var plugins = service.RetrieveMultiple(p).Entities
                    .Select(x => new
                        {
                            Id = x.Id,
                            Name = x.Attributes["name"] as string,
                            EventHandlerName = x.Attributes["eventhandlername"] as string,
                            SdkMessageIdName = x.Attributes["sdkmessageidname"] as string,
                            IsDisabled = ((int) x.Attributes["statecode"]) == 1
                                        && ((int) x.Attributes["statuscode"]) == 2,
                        }
                    );

有効 / 無効の切り替えを行う

SQLを直に投げるのはやんわりと禁止されてるので、SDKのやり方だけ。

普通にSetStateRequestをExecuteから投げてあげれば大丈夫です。

// Workflow
foreach (var workFlow in workFlows)
{
    // 無効なら有効に、有効なら無効に切り替える
    var statecode = workFlow.IsDisabled ? 1 : 0;
    var statuscode = workFlow.IsDisabled ? 2 : 1;
    
    service.Execute(new SetStateRequest
    {
        EntityMoniker = new EntityReference("workflow", workFlow.Id),
        State = new OptionSetValue(statecode),
        Status = new OptionSetValue(statuscode),
    });
    
}

// Plugin
foreach (var plugin in plugins)
{
    // 無効なら有効に、有効なら無効に切り替える
    var statecode = plugin.IsDisabled ? 0 : 1;
    var statuscode = workFlow.IsDisabled ? 1 : 2;
    
    service.Execute(new SetStateRequest
    {
        EntityMoniker = new EntityReference("sdkmessageprocessingstep", plugin.Id),
        State = new OptionSetValue(statecode),
        Status = new OptionSetValue(statuscode),
    });
}

まとめ

RESTを使っても出来るんじゃないかなぁ、と思います。試してないですが。

なんにしろ、この辺の操作も自動化できるってことはtipsとして知っておいて損はないです。

参考