【Dataverse】Visual StudioによるDataverse Plugin(Pre Validation)

accountテーブルのtelephone1の入力チェックを作成する場合の手順は以下の通りです。
入力チェックは正規表現で「^[0-9]+$」とします。

クラスファイルはプロジェクト内に2つあっても問題ありません。
1つのAssembly(dllファイル)に2つのPluginが出来上がる形になります。
クラスファイルの中身以外は以前の手順踏襲となります。

  • クラスファイルの編集
    クラス名を変更し、開発を行います。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    using System.Text.RegularExpressions;
    
    namespace MyDataversePluginVS462
    {
        public class FollowupPlugin2 : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                // プラグイン実行コンテキストの取得
                IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext)) as IPluginExecutionContext;
                if (context == null)
                {
                    throw new InvalidPluginExecutionException("プラグイン実行コンテキストが取得できませんでした。");
                }
    
                // 組織サービスファクトリの取得
                IOrganizationServiceFactory serviceFactory = serviceProvider.GetService(typeof(IOrganizationServiceFactory)) as IOrganizationServiceFactory;
                if (serviceFactory == null)
                {
                    throw new InvalidOperationException("IOrganizationServiceFactory が取得できませんでした。");
                }
    
                // トレーシングサービスの取得
                ITracingService tracingService = serviceProvider.GetService(typeof(ITracingService)) as ITracingService;
                if (tracingService == null)
                {
                    throw new InvalidPluginExecutionException("トレーシングサービスが取得できませんでした。");
                }
    
                // ターゲットエンティティがAccountであるか
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity account && account.LogicalName == "account")
                {
                    tracingService.Trace("PhoneCheckプラグインが実行されました。");
    
                    // ターゲットエンティティのCreateかどうか
                    if (context.MessageName == "Create")
                    {
                        // 電話番号フィールドが存在するか
                        if (account.Attributes.Contains("telephone1"))
                        {
                            string phoneNumber = account.Attributes["telephone1"] as string;
                            if (!string.IsNullOrEmpty(phoneNumber) && Regex.IsMatch(phoneNumber, "^[0-9]+$"))
                            {
                                tracingService.Trace("電話番号の書式は問題ありません。");
                            }
                            else
                            {
                                throw new InvalidPluginExecutionException("新規登録時は電話番号の書式は数値のみで入力してください。");
                            }
                        }
                        else
                        {
                            throw new InvalidPluginExecutionException("電話番号(telephone1)フィールドが存在しません。");
                        }
                    }
                    else
                    {
                        throw new InvalidPluginExecutionException("プラグインが実行できませんでした。(メッセージ違い)");
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("プラグインが実行できませんでした。(テーブル違い)");
                }
    
                // 処理全体をtry-catchで囲って、catchでInvalidPluginExecutionExceptionするのもあり。
            }
        }
    }
    

【Dataverse】Dataverse Pluginの追加

accountテーブルのtelephone1に「81-」を付与するPluginを登録する場合の手順は以下の通りです。

  • Plugin Registration Tool起動
    Plugin Registration Toolを起動し、「CREATE NEW CONNECTION」を選択します。
    「Display list of available organizations」を選択するとMicorosft 365に接続するウィンドウが起動するのでサインインを行います。
  • dllファイルの登録
    画面上部の「Register」-「Register New Assembly」を選択します。
    コンパイル後のdllファイルを選択します。
    Sandbox、Dataverseが選択されていることを確認し、「Register Selected Plugins」を押下します。
    AssemblyとPluginが登録されます。
  • PluginのStep登録
    登録されたPluginを選択し、右クリックし、「Register New Step」を選択します。
    以下をそれぞれ設定し、「Register New Step」を押下します。
    Message:Create
    Primary Entity:account
    Event Pipeline Stage of Execution:Pre Operation
    Exection Mode:Synchronous(同期)
  • トレースログON
    D365詳細設定画面を開き、「システム」-「管理」-「カスタマイズ」を開く。
    「プラグインおよびユーザー定義ワークフロー活動の追跡」を「Off」から「All」に変更する。
    トレースログは「システム」-「カスタマイズ」-「プラグイントレースログ」で確認できる。
  • 動作確認
    Power Apps(キャンパスアプリ)、Power Apps(モデル駆動型アプリ)、Power Automateのどれで登録しても
    telephone1に登録後に「81-」が付与される。

【Dataverse】Visual StudioによるDataverse Plugin(Pre Operation)

accountテーブルのtelephone1に「81-」を付与するPluginを作成する場合の手順は以下の通りです。

  • Visual Studioの導入
    Visual Studio 2022の無料版をインストールします。
    「Visual Studio 2022」「Visual Studio Installer」「Blend for Visual Studio 2022」の3つがアプリとして表示されます。

    Visual Studio 2022
    →通常の開発用
    
    Visual Studio Installer
    →.NetFrameworkやWEBアプリ開発に必要なパッケージのインストールツール
    
    Blend for Visual Studio 2022
    →アニメーション、storyboards、behaviorsの開発用
     Visual Studio 2022のプロジェクトファイルと互換性あり
    
  • プロジェクト作成
    「クラスライブラリ(.NetFramework)」のプロジェクトを作成し、
    フレームワークに「.NetFramework4.6.2」を選択します。
  • NuGetパッケージの管理
    ソリューションエクスプローラーでプロジェクトを右クリックし、「NuGetパッケージの管理」を選択します。
    「Microsoft.CrmSdk.CoreAssemblies」の最新版をインストールします。
  • クラスファイルの編集
    クラス名を変更し、開発を行います。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    
    namespace MyDataversePluginVS462
    {
        public class FollowupPlugin : IPlugin
        {
            public void Execute(IServiceProvider serviceProvider)
            {
                // プラグイン実行コンテキストの取得
                IPluginExecutionContext context = serviceProvider.GetService(typeof(IPluginExecutionContext)) as IPluginExecutionContext;
                if (context == null)
                {
                    throw new InvalidPluginExecutionException("プラグイン実行コンテキストが取得できませんでした。");
                }
    
                // 組織サービスファクトリの取得
                IOrganizationServiceFactory serviceFactory = serviceProvider.GetService(typeof(IOrganizationServiceFactory)) as IOrganizationServiceFactory;
                if (serviceFactory == null)
                {
                    throw new InvalidOperationException("IOrganizationServiceFactory が取得できませんでした。");
                }
    
                // トレーシングサービスの取得
                ITracingService tracingService = serviceProvider.GetService(typeof(ITracingService)) as ITracingService;
                if (tracingService == null)
                {
                    throw new InvalidPluginExecutionException("トレーシングサービスが取得できませんでした。");
                }
    
                // イベントの種類がCreateであり、ターゲットエンティティがAccountであるか
                if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity account && account.LogicalName == "account")
                {
                    tracingService.Trace("AddPhonePrefixプラグインが実行されました。");
    
                    // 電話番号フィールドが存在するか
                    if (account.Attributes.Contains("telephone1"))
                    {
                        string phoneNumber = account.Attributes["telephone1"] as string;
                        if (!string.IsNullOrEmpty(phoneNumber))
                        {
                            // 電話番号にプレフィックスを追加
                            account.Attributes["telephone1"] = "+81-" + phoneNumber;
                            tracingService.Trace($"電話暗号を'{phoneNumber}'から'+81-{phoneNumber}'に変更しました。");
                        }
                    }
                }
                else
                {
                    throw new InvalidPluginExecutionException("プラグインが実行できませんでした。");
                }
    
                //throw new NotImplementedException();
            }
        }
    }
    
  • アセンブラの署名
    ソリューションエクスプローラーでプロジェクトを右クリックし、「プロパティ」を選択します。
    左メニューから「署名」を選択し、キーファイルに任意の名前を入力します。
    「キーファイルをパスワードで保護します」のチェックを外します。
    署名アルゴリズムはデフォルトのままで署名を行います。
  • ソリューションのビルド
    ソリューションのビルドを行います。
    プロジェクトファイルの場所にもよりますが、デフォルトの場合、以下にdllファイルが出力されます。
    C:\Users\ユーザー名\source\repos\MyDataversePluginVS462\MyDataversePluginVS462\bin\Debug

【Dataverse】VSCodeによるDataverse Plugin

  • VScodeのPlugin
    Power Platform Tools
    Japanese Language Pack for Visual Studio Code
    C# Dev Kit
    C# ※自動?
    .NET Install Tool ※自動?
  • VScodeの開発1(失敗例)

    ターミナル
    mkdir MyDataversePlugin
    cd MyDataversePlugin
    pac plugin init --skip-signing ※これでプロジェクトが自動作成 ただし、この方法は署名なし
    dotnet add package Microsoft.CrmSdk.CoreAssemblies
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly
    

    C#で開発します。

    ターミナル
    dotnet build -c Release
    

    ビルドが成功すると以下にdllファイルが作成される。
    C:\Users\ユーザ名\MyDataversePlugin\bin\Release\net462\publish\MyDataversePlugin.dll

    Plug-in Registration Tool (PRT) を起動します。

    ターミナル
    pac tool prt ※コマンド実行後にWindowsに自動インストール
    サインインは「Office365」、「Display list of avaiable organizations」を選択
    

    この後にアセンブリを登録しようとすると署名エラーとなってしまう。

  • VScodeの開発2(失敗例)

    ターミナル
    mkdir MyDataversePlugin
    cd MyDataversePlugin
    dotnet new classlib -lang C# -o . ※失敗例1との違いはココ
    dotnet add package Microsoft.CrmSdk.CoreAssemblies
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly
    

    C#で開発します。

    ターミナル
    dotnet build -c Release
    

    ビルドが成功すると以下にdllファイルが作成される。
    C:\Users\ユーザ名\MyDataversePlugin\bin\Release\net462\publish\MyDataversePlugin.dll

    Plug-in Registration Tool (PRT) を起動します。

    ターミナル
    pac tool prt ※コマンド実行後にWindowsに自動インストール
    サインインは「Office365」、「Display list of avaiable organizations」を選択
    

    この後にアセンブリを登録しようとすると参照ライブラリのバージョンでエラーとなってしまう。

  • 失敗原因

    ビルド時に作成されるフォルダが「net462」となっているように
    .NETFrameworkが4.62になっている必要があるようです。
    VScodeインストールした際に.NET9.0をインストールしていました。

    .NETFrameworkはWindows専用であるのに対し、
    .NETはクロスプラットフォーム(Windows, Linux, macOS)の違いがあるようです。


    またアセンブリにもパスワードなしの署名が必要なようです。


    以下の参照は不要。
    dotnet add package Microsoft.CrmSdk.XrmTooling.CoreAssembly

  • 参考サイト
    https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/build-and-package
    「プラグインおよびカスタム ワークフロー活動アセンブリ プロジェクトは、.NET Framework 4.6.2 をターゲットにする必要があります」の記述あり。

    https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/tutorial-write-plug-in
    上記のサイトを見るとVisual Studioを使っていたのでVisual Studio2022を使うことにしました。
    プロジェクトを作成する際、.NETクラスライブラリではなく、
    .NETFrameworkクラスライブラリプロジェクトを作成することに注意。

【Power Apps】モデル駆動型アプリのビジネスプロセスフロー

  • モデル駆動型アプリのビジネスプロセスフロー
    条件分岐によってフローを切り替えることも可能。
    合流させることも可能。

    合流させるには、合流させたいステージを選択して[コネクタ]→[接続]を押下して
    合流後のステージを選ぶと合流できる。

    参考サイト
    ttps://ippu-biz.com/development/powerplatform/powerapps/mda/bpf-condition/

【Power Apps】ダッシュボードとグラフ

  • ダッシュボード
    ダッシュボードは事前に準備した一覧画面(ビュー)やグラフを決まった枠内に配置できる機能。
    ・テーブルそのものを表示することも可能。
    ・テーブルを基に目的に合わせて行列を絞り込んだビューを表示することも可能。
    ・ビューを基に作成したグラフを表示することも可能。
  • グラフ
    グラフはビューに連動しており、ダッシュボード内で絞り込み条件を変更することで
    グラフも動的に変わる。

    予実比較ようなグラフも作成できる。
    横軸:年、タイプ(見積/実績)
    縦軸:比較項目(月ごとの金額とか)
    参考サイト
    ttps://www.arcuss-japan.com/crmblogs/2020/01/07/3161/

【Power Automate】Excelファイルの操作

  • Excelファイルを開く
    監視が成功するとJSONが戻ってくるので、その中から34桁のブックIDを取得し、
    それをExcel操作用に利用する必要がある。
    参考サイト
    ttps://qiita.com/fukasuke/items/1502b9b9b045c78f67e9

    具体的な取得方法としては戻り値の中から「Thumbnail」を取得する。
    Thumbnailを「&」で分解すると以下の形式となるので、
    「docid」をsubstringやindexOfを駆使して取得する。

    https://japaneast1-mediap.svc.ms/transform/thumbnail
    ?provider=spo
    &inputFormat=xlsx
    &cs=fFNQTw
    &docid=https%3a%2f%2f・・・
    &width=xxx
    &height=xxx
    

【Power Automate】動的コンテンツと式

  • 動的コンテンツと式
    Power Automateで選択した動的コンテンツはすべて式で表現できる。
    例)以下は同じ意味

    substring(variables('変数名'), indexOf(variables('変数名'), 'https%3a%2f%2f'))
    substring(動的コンテンツから指定, indexOf(動的コンテンツから指定, 'https%3a%2f%2f'))
    

    動的コンテンツから指定=variables(‘変数名’)は同じオブジェクトを指している。