Dynamics CRM ではプラグインを使用してエンティティの検索や登録、更新時にデータの検証やカスタム処理を行えるようにできます。今回はDynamics のユーザ登録時にアカウントを調べ、CRMで始まるアカウント名でない場合は、登録をさせないようにするプラグインを作成します。

Dynamics CRM プラグインのVisual Studio 2008 用テンプレートが公開されています。
- Visual Studio Template for Microsoft Dynamics CRM Plug-ins
http://code.msdn.microsoft.com/crmplugintemplate
- Microsoft Dynamics CRM Plug-in Template for Visual Studio
http://blogs.msdn.com/crm/archive/2008/10/27/microsoft-dynamics-crm-plug-in-template-for-visual-studio.aspx

確認環境

  • 動作環境:Windows Server 2003 Dynamics CRM 4.0 IFD構成
  • 開発環境:Visual Studio 2008 Professional
  • .NET 3.0

1. 作成するプラグインの動作

プラグインの動作例を示します。下図のようにアカウントがcrmで始まらないユーザを作成使用とします。このとき、メニューの保存ボタンをクリックします。

エラーダイアログが表示され、登録が行えないようになります。

2. プラグインの作成

まずは、Visual Studio 2008 を起動して、空のソリューションを作成します。ソリューション名はFirstCrmPlugin としました。次にソリューションエクスプローラを右クリックして追加→新しいプロジェクトをクリックしプロジェクトの追加します。プロジェクトのテンプレートはクラスライブラリを選択し、プロジェクト名はPlugins として作成します。

2.1 アセンブリ参照と署名の設定

通常のDynamics の拡張アプリケーションを作成するのと同じようにDynamics CRM SDK 付属の microsoft.crm.sdk.dll と microsoft.crm.sdktypeproxy.dll の参照を追加します。また、System.Web.Services.dll の参照も追加します。

今回のプラグインはCRMのデータベースに登録するので、アセンブリを署名します。Plugins プロジェクトのプロパティ画面を表示し、下図のように署名タブを選択し、アセンブリの署名のチェックをし、"厳密な名前のキー ファイルを選択してください"プルダウンで新規を選択して、FirstCrmPlugin.Plugins.snk  というファイル名で署名用のファイルを作成します。

2.2 プラグインクラスの作成

既定で作成されるClass1.cs を削除し、新規クラスファイル SystemUserValidator.cs を作成し、次のように編集します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using System.Text.RegularExpressions;

namespace Plugins
{
    /// <summary>
    /// システムユーザの登録、更新時にアカウント名がP番,S番で
    /// 始まるかを確認するプラグイン
    /// </summary>
    public class SystemUserValidator : IPlugin
    {
        #region IPlugin メンバ

        public void Execute(IPluginExecutionContext context)
        {
            DynamicEntity entity = context.InputParameters[ParameterName.Target] as DynamicEntity;
            if (entity != null && entity.Properties.Contains("domainname"))
            {
                string logonId = entity.Properties["domainname"] as string;
                int pos = logonId.IndexOf('\\');
                if (pos >= 0)
                {
                    logonId = logonId.Substring(pos + 1);
                }
                Regex regex = new Regex("^CRM", RegexOptions.IgnoreCase);
                if (!regex.IsMatch(logonId))
                {
                    throw new InvalidPluginExecutionException("CRMで始まるユーザIDではありません" + context.Stage.ToString());
                }
            }
        }

        #endregion
    }
}

プラグインはEntity の登録時に呼び出されるので、contextのInputParameters で ParameterName.Target をインデクサに設定して登録された Entity を取得します。 クラスはDynamicsEntity となります。SystemUsers の domainname 属性を調べてCRMで始まるアカウント名かを調べ、一致しない場合はInvalidPluginExecutionException をスローするようにしています。

プロジェクトをビルドし、Plugins.dllが作成されれば成功です。

サポートされているプラグインのメッセージやImageプロパティに指定できる項目などは[DynamicsCRM] プラグインで使用できるメッセージのメモ を参照してください。

3. プラグインの登録

Dynamics CRM SDK に付属するプラグイン登録ツール plugindeveloper を使用して登録します。plugindeveloper の競ってファイルregister.xml を次のように設定して登録を行いました。構成ファイルでは、同じディレクトリ配下にあるPlugins.dll アセンブリを登録し、Step タグで、systemuserエンティティのCreateメッセージ時に事前イベントでプラグインPlugins.SystemUserValidator を同期的に実行するように設定しています。Org(組織名), Domain(ドメイン名), UserName(接続ユーザ名) は環境に応じて変更してください。

<Register  LogFile = "Plug-in Registration Log.txt"
    Server  = "http://localhost"
    Org     = "crmorg01"
    Domain  = "crm1"
    UserName= "crmadmin" 
    >

    <Solution SourceType="0" Assembly=".\Plugins.dll">

        <!--
        Tag: Steps
        Description: Stepタグのコンテナ. -->

        <Steps>

            <!--
            Tag: Step
            Description: アセンブリ内のプラグインの一つを登録する.
            Attributes:
                CustomConfiguration
                    プラグインのコンストラクタに渡されるオプション文字列.
                Description
                    プラグインの説明.
                FilteringAttributes
                    カンマ区切りの属性値のリストを指定する。指定された属性値に変更がある場合にプラグインが実行される.
                    null値の場合はすべての属性値が対象となる.
                ImpersonatingUserId
                    プラグインの実行ユーザを偽装する場合に、偽装する systemuser の GUID を指定する.
                InvocationSource
                    プラグインがparentもしくはchildパイブラインで実行されるかを指定する.
                    設定可能な値:0 (parent) or 1 (child).
                MessageName
                    プラグインが実行されるメッセージ名.最初の1文字は大文字であること.
                Mode
                    プラグインが同期、非同期のどちらかで実行されるかを指定する.
                    設定可能な値:0 ( synchronous) or 1 (asynchronous).
                PluginTypeFriendlyName
                    プラグインのフレンドリ名を指定する
                PluginTypeName
                    プラグイン型の完全名.
                PrimaryEntityName
                    プラグインを実行するプライマリエンティティ名.
                    標準的なエンティティでは、エンティティ名は小文字となる.
                SecondaryEntityName
                    プライマリエンティテと関連するセカンダリエンティティ名.
                    標準的なエンティティでは、エンティティ名は小文字となる.
                Stage
                    プラグインが登録される実行パイプラインイベントのステージ
                    設定可能な値: 10 (pre-event) or 50 (post-event).
                SupportedDeployment
                    サポートされる配備ロケーション.
                    設定可能な値: 0 (server), 1 (Outlook client), or 2 (both).
            SDK documentation: SdkMessageProcessingStepRegistration class -->

            <Step
                CustomConfiguration = ""
                Description = "Auditing Plugin"
                FilteringAttributes = ""
                ImpersonatingUserId = ""
                InvocationSource = "0"
                MessageName = "Create"
                Mode = "0"
                PluginTypeFriendlyName = "SystemUser Audit"
                PluginTypeName = "Plugins.SystemUserValidator"
                PrimaryEntityName = "systemuser"
                SecondaryEntityName = ""
                Stage = "10"
                SupportedDeployment = "0" >

                <!--
                Tag: Images
                Description: Container for one or more Image tags. -->

                <Images>

                    <!-- 
                    Tag: Image
                    Description: 登録するプラグインで実行時に参照できるエンティティの属性値名のリスト.
                    Attributes:
                        EntityAlias
                            Imageプロパティコレクションからimageにアクセスするためのキー値
                        ImageType
                            いつImageのスナップショットを行うかを指定.
                            設定可能な値: 0 (before core operation), 1 (after core operation), or 2 (both).
                        MessagePropertyName
                            Request メッセージのメッセージプロパティ名.
                        Attributes
                            プラグインに渡されるカンマ区切りのターゲットエンティティの属性名.
                    SDK documentation: SdkMessageProcessingStepImageRegistration class
                    Comment: 使用例はplugindeveloperのサンプル設定参照 -->
                </Images>
            </Step>
        </Steps>
    </Solution>
</Register>

プラグイン登録設定ファイルを次のように編集した後、コマンドプロンプトからplugindeveloper を実行し、CRM登録用のユーザのパスワードを入力しててプラグインを登録します。

plugindeveloperとpluginregistration tool はフォーム認証を行うIFD構成では実行できません。認証エラーが発生します。プラグインを登録するにはAD認証を行う必要があります。IFD構成の場合は、CRMサーバ上でplugindeveloperを実行し、サーバをlocalhostで参照するようにします。詳しくはブログを参照
http://blogs.msdn.com/crm/archive/2008/07/01/plug-in-registration-tool-2-1.aspx
コードギャラリーでもIFD構成の場合の問題が掲載されています。
http://code.msdn.microsoft.com/crmplugin/WorkItem/View.aspx?WorkItemId=12

4. おわり

以上でプラグインの作成と登録の説明は終了です。誤り、指摘点等がありましたらご連絡ください。

以上