今年最後のネタはSharePointネタです。SharePointでワークフローをライブラリに適用する際に、
自分でワークフローを起動する。
アイテムが新規投稿されたときに起動する。
アイテムが編集されたときに起動する。
という起動オプションがあるのですが、3番目の「アイテムが編集されたときに起動する」というオプションはユーザに気付かせずにワークフローを裏で動かすために便利なのですが、なかなか扱いづらいものでして、
アイテムが編集される。
ワークフローが起動される。
ワークフローにてアイテムに編集をかける。
アイテムが編集されたのでさらにワークフローが起動される。(延々とループ)
・・・・
というかなり斬新な仕様になってます。で、いろいろ困って検索していましたら、こんな対応方法がありましたので紹介してみます。
動かしてみたら、確かにワークフローインスタンスがパカパカつくられた形跡はなく、うまく動くようでした。
自分でワークフローを起動する。
アイテムが新規投稿されたときに起動する。
アイテムが編集されたときに起動する。
という起動オプションがあるのですが、3番目の「アイテムが編集されたときに起動する」というオプションはユーザに気付かせずにワークフローを裏で動かすために便利なのですが、なかなか扱いづらいものでして、
アイテムが編集される。
ワークフローが起動される。
ワークフローにてアイテムに編集をかける。
アイテムが編集されたのでさらにワークフローが起動される。(延々とループ)
・・・・
というかなり斬新な仕様になってます。で、いろいろ困って検索していましたら、こんな対応方法がありましたので紹介してみます。
動かしてみたら、確かにワークフローインスタンスがパカパカつくられた形跡はなく、うまく動くようでした。
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Xml.Serialization;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WorkflowActions;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
/// provides access to the internal Microsoft.SharePoint.SPEventManager class by using reflection
/// sample usage:
/// SPEventManagerWrapper.DisableEventFiring();
/// SPList myList = SPContext.Current.Web.Lists["Shared Documents"];
/// myList.Items[0].Update();
/// SPEventManagerWrapper.EnableEventFiring();
namespace setDraftWorkflow
{
public static class SPEventManagerWrapper
{
private static readonly string _className = "Microsoft.SharePoint.SPEventManager";
private static readonly string _eventFiringSwitchName = "EventFiringDisabled";
private static Type _eventManagerType;
/// gets the status of event firing on the current thread
public static bool EventFiringDisabled
{
get { return GetEventFiringSwitchValue(); }
}
private static Type EventManagerType
{
get
{
if (_eventManagerType == null)
GetEventManagerType();
return _eventManagerType;
}
}
/// enables event firing on the current thread
public static void EnableEventFiring()
{
SetEventFiringSwitch(false);
}
/// disables sharepoint event firing on the current thread
public static void DisableEventFiring()
{
SetEventFiringSwitch(true);
}
/// sets the event firing switch on Microsoft.SharePoint.SPEventManager class using reflection
private static void SetEventFiringSwitch(bool value)
{
PropertyInfo pi = EventManagerType.GetProperty(_eventFiringSwitchName, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
pi.SetValue(null, value, null);
}
private static bool GetEventFiringSwitchValue()
{
PropertyInfo pi = EventManagerType.GetProperty(_eventFiringSwitchName, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
object val = pi.GetValue(null, null);
return (bool)val;
}
private static Type GetEventManagerType()
{
_eventManagerType = typeof(SPList).Assembly.GetType(_className, true);
return _eventManagerType;
}
}
public sealed partial class Workflow1: SequentialWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties workflowProperties = new Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties();
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
SPListItem activator = workflowProperties.Item;
// なんか自アイテムを編集する。
SPEventManagerWrapper.DisableEventFiring();
activator.Update();
SPEventManagerWrapper.EnableEventFiring();
}
}
}


