SharePoint Online にて、2010 形式ワークフローでエラー発生したアイテムの一覧を取得するサンプル

こんにちは、SharePoint サポートの森 健吾 (kenmori) です。

今回の投稿では、SharePoint Online で2010 形式ワークフローを使用して運用してエラー発生した際に、エラー発生しているアイテムの一覧を取得し、メール通知するサンプル コードをご案内します。
以前の投稿である On-Premises 版のサンプル コードは過去のブログ (下記) をご参考にしてください。

タイトル : 内部エラー (WinWF Internal Error) 発生を想定したSharePoint ワークフローをデザインする
アドレス : https://blogs.technet.com/b/sharepoint_support/archive/2012/11/27/a-sharepoint.aspx

 

クラウド上の高スペック マシンにホストされた SharePoint Online でも、On-premises 同様、様々な事情によりワークフローでエラーが発生することはあります。他のあらゆるシステム同様、ワークフローでもエラーが発生することを 100% 防ぐことはできません。

ワークフローは一部の処理でリトライ機能をもつものの、一般的にはエラーが発生した際にはエラー発生という状態を表示し、特に処理を行うことはありません。そのため、エラーが発生する時に、どういったアクションをとるかは引き続き運用側に委ねられています。
特に重要なビジネス ロジックを含むワークフローにおきましては、エラー発生した際に即座に対処をとりたい場合も多いでしょう。

On-Premises 版のサンプルでは自動的に再起動する処理までを実装しておりました。ところが、SharePoint Online では、サーバー上で動作させる SSOM (Server Side Object Model) を使用することができず、代わりにリモート実行のライブラリである CSOM (Client Side Object Model) で同じ動作を実装する方法を検討する必要がありました。

検討の結果、SSOM の SPListItem.Workflows プロパティに相当する処理が CSOM 側にないことを確認しました。ワークフロー インスタンスを取得してワークフローを自動終了させることができないため、代わりに通知するという方法を選択しております。

補足2013 形式ワークフローでは、ワークフローに関する幅広い API を使用することができ、ワークフローの再起動も可能と想定されます。しかしながら、代理ステップで利用できたアクションなど (権限変更等) を "HttpWeb サービスを呼び出す" アクションを利用して作成する必要があるため、一般ユーザーでの利用が難しい等、機能的な制約により 2010 形式ワークフローを選択せざるを得ないことも否定できません。

ワークフロー設計における注意事項は On-premises で記載した内容と同じですので、今回はサンプル プログラムのみ、下記に記載させていただきます。今後の運用にお役立ていただけますと幸いです。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SP = Microsoft.SharePoint.Client;

 

namespace NotifyFailedWorkflow
{
    class Program
    {
        static void Main(string[] args)
        {
            string siteUrl = "https://tenant.sharepoint.com/sites/workflow"; // サイトの URL を指定します。
            string listTitle = "WorkflowList"; // リスト名を指定します。
            string username = "tenantadmin@tenant.onmicrosoft.com"; // ユーザー ID を指定します。
            string pwd = "password"; // パスワードを指定します。
            string emailfrom = "tenantadmin @tenant.onmicrosoft.com"; // メール送信元を指定します。
            string[] emailto = {"tenantadmin@tenant.onmicrosoft.com", "siteadmin@tenant.onmicrosoft.com"}; // メール送信先 (複数指定可) を指定します。 

            try
            {
                SP.ClientContext context = new SP.ClientContext(siteUrl);
                System.Security.SecureString secpas = new System.Security.SecureString();
                foreach (char c in pwd.ToCharArray())
                {
                    secpas.AppendChar(c);
                }

                SP.SharePointOnlineCredentials userCredentials = new SP.SharePointOnlineCredentials(username, secpas);
                context.Credentials = userCredentials;

                SP.Web web = context.Web;
                SP.List list = web.Lists.GetByTitle(listTitle);
                context.Load(web);
                context.Load(list.DefaultView);
                context.Load(list.Fields);
                context.ExecuteQuery(); 

                StringBuilder sb = new StringBuilder();

                foreach (SP.Field field in list.Fields)
                {
                    // ワークフロー状態列を列挙します。
                    if (field.TypeAsString == "WorkflowStatus")
                    {
                        // 取得したワークフロー状態列がエラー発生 (3) の値のアイテムを取得します。(下記表を参照ください。)
                        SP.CamlQuery query = new SP.CamlQuery();
                        query.ViewXml = string.Format("<View><Query><Where><Contains><FieldRef Name='{0}'/><Value Type='Text'>{1}</Value></Contains></Where></Query></View>", field.InternalName, 3);

                        SP.ListItemCollection listitems = list.GetItems(query);
                        context.Load(listitems);
                        context.ExecuteQuery(); 

                        if (listitems.Count > 0)
                        {
                            sb.AppendLine(string.Format("<BR><BR>リスト <a href='{0}{1}'>{2}</a> の下記アイテムでワークフロー ({3}) のエラーが発生しています。<BR><BR>ID\tTitle<BR>",
                                web.Url.Substring(0, web.Url.IndexOf("/", "https://".Length)),
                                list.DefaultView.ServerRelativeUrl,
                                listTitle,
                                field.InternalName));

                            foreach (SP.ListItem item in listitems)
                            {
                                sb.Append(item.Id.ToString());
                                sb.Append("\t");
                                sb.Append(item["Title"].ToString());
                                sb.Append("<BR>");
                            }
                        }
                    }
                }

                if (sb.Length > 0)
                {
                    SP.Utilities.EmailProperties prop = new SP.Utilities.EmailProperties();
                    List<string> ToList = new List<string>();
                    ToList.AddRange(emailto);
                    prop.To = ToList;
                    prop.From = emailfrom;
                    prop.Subject = string.Format("ワークフロー エラー発生 : {0}", listTitle);
                    prop.Body = sb.ToString();
                    SP.Utilities.Utility.SendEmail(context, prop);
                    context.ExecuteQuery();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                //Console.Read();
            }
        }
    }
}

送信メールのイメージ

本サンプル コードで送信されるメールのイメージは下記の通りです。

前提事項

開発環境および実行環境においては、下記 SharePoint Online Client Components SDK をインストールしておくことが前提事項となります。

タイトル : SharePoint Online Client Components SDK
アドレス : https://www.microsoft.com/en-us/download/details.aspx?id=42038

補足
以前の投稿にも記載した通りとなりますが、ワークフローの状態列の値は下記をご参照ください。

 

今回の投稿は以上となります。