<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkICQHw5eyp7ImA9WhdTEEU.&quot;"><id>tag:blogger.com,1999:blog-4570237346466838189</id><updated>2011-07-07T17:22:41.223-07:00</updated><title>Making .Net Concepts Work</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://makingdotnetwork.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://makingdotnetwork.blogspot.com/" /><author><name>Paul Divan</name><uri>http://www.blogger.com/profile/03003052730236405176</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_Vs2hnSFhfYI/SPYglplUgKI/AAAAAAAAACI/EDWqHN3w408/S220/MugShot.JPG" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>3</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MakingDotNetConceptsWork" /><feedburner:info uri="makingdotnetconceptswork" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEADRHk6fCp7ImA9WxRaEkU.&quot;"><id>tag:blogger.com,1999:blog-4570237346466838189.post-8283064373358058366</id><published>2008-12-14T11:26:00.001-08:00</published><updated>2008-12-14T11:26:15.714-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-14T11:26:15.714-08:00</app:edited><title>How to Create a Custom ILM Workflow Activity - Part III: Creating the Custom Workflow Activity UI</title><content type="html">&lt;p&gt;This is the third part of a three part series on creating a custom workflow activity for ILM 2.0. A reminder that in order to create and build this solution you will need an implementation of the ILM 2.0 Beta 3&amp;#160; server or the RC Candidate with a copy of Visual Studio 2008 Professional Developer edition installed on it.&lt;/p&gt;  &lt;p&gt;Sorry for taking so long to get this part out. I got stuck in a bit of the economic downturn we are all experiencing and fortunately, instead of having nothing to do, have spent the last 6 weeks building a software application for a customer and this is the first time I have come up for air. &lt;/p&gt;  &lt;p&gt;If you want to download the source for this project you can find it here: &lt;a href="http://www.codeplex.com/ILM2WFActivity"&gt;ILM 2 Customer WF Activity&lt;/a&gt; on CodePlex. &lt;/p&gt;  &lt;p&gt;I want to again mention my two colleagues &lt;a href="http://www.identitychaos.com/"&gt;Brad Turner&lt;/a&gt; and &lt;a href="http://ilmbestpractices.com/"&gt;David Lundell&lt;/a&gt; for their support and contributions to this effort as well as ILM itself. Both are ILM MVPs and their blogs are worth exploring whenever you have questions about ILM.&lt;/p&gt;  &lt;p&gt;In Part I, I laid out all the steps required to create the project and get it ready for developing the code. In Part II I we looked at how the project develops to the point where we have the ILM compatible workflow foundation activity defined and in Part III I will show you how to add the UI class that allows the activity to be listed in the available activities in ILM Process Designer. We'll also dig into how to install and configure the custom activity, add it to an existing Process workflow and see the results of our work.&lt;/p&gt;  &lt;p&gt;Now let us create the class that will allow us to see our custom activity in the ILM Process Design Surface. Follow these steps to build the ILM Activity:&lt;/p&gt;  &lt;p&gt;First let us create a new class named EnsynchDianosticActivityUI.cs. We also need to add the references we need to support ILM as well as the workflow engine and, since we will actually be building a .Net web control, we need to add the ASP.Net references as well.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.ComponentModel;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.ComponentModel.Design;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.ComponentModel.Compiler;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.ComponentModel.Serialization;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.Runtime;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.Activities;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Workflow.Activities.Rules;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.WebControls;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.UI.HtmlControls;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.ResourceManagement.Utilities;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.IdentityManagement.WebUI;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.ResourceManagement.Workflow.Activities;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.IdentityManagement.WebUI.Controls;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.IdentityManagement.WebUI.Controls.Resources;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We are also going to change the namespace that I use for the interactive components to: EnSynch.ILM.Activities. This class needs to implement the &amp;quot;ActivitySettingsPart&amp;quot; interface so well add that to our class definition and allow it to flow out the implementation of our class for us (see below)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP4z-ZIXQuI/AAAAAAAAAEA/cPbiqYy-vgw/s1600-h/clip_image0013.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="68" alt="clip_image001" src="http://lh5.ggpht.com/pauldivaniii/SP4z-0FXg7I/AAAAAAAAAEE/LShlSvfL4fA/clip_image001_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The resulting class structure for us to flesh out is shown below:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP4z_eu72VI/AAAAAAAAAEI/_MQ2ZrvR3v0/s1600-h/clip_image0023.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="213" alt="clip_image002" src="http://lh5.ggpht.com/pauldivaniii/SP4z__F_NZI/AAAAAAAAAEM/GBpBsGF4Anc/clip_image002_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So again, we are going to add some helper functions that will help us create our user interface. These will create all the user interface components we need to show the user in order for them to provision this activity in the ILM Process Design Surface. Note: The EnsynchSwish.jpg file is included in the root folder of the solution in case you want to use it to see how it appears on the design surface. I created an Images folder in my SharePoint website root and am referencing the image file from there in the code below.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;         &lt;span class="preproc"&gt;#region&lt;/span&gt; Utility Functions&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InitializeControls()&lt;br /&gt;        {&lt;br /&gt;            Table child = &lt;span class="kwrd"&gt;new&lt;/span&gt; Table();&lt;br /&gt;            child.Style.Add(&lt;span class="str"&gt;&amp;quot;background-image&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;/Images/EnsynchSwish.jpg&amp;quot;&lt;/span&gt;);&lt;br /&gt;            child.Width = Unit.Percentage(100.0);&lt;br /&gt;            child.BorderWidth = 0;&lt;br /&gt;            child.CellPadding = 2;&lt;br /&gt;            &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;// We need an activity name for our instance, a folder path to where to write the file and a text box to hold our filename&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;// which we will default to myLog.txt&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;            child.Rows.Add(AddTableRow(&lt;span class="str"&gt;&amp;quot;Activity Name:&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;, 64, &lt;span class="kwrd"&gt;false&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Diagnostics&amp;quot;&lt;/span&gt;));&lt;br /&gt;            child.Rows.Add(AddTableRow(&lt;span class="str"&gt;&amp;quot;File Folder Path:&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;, 256, &lt;span class="kwrd"&gt;false&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;C:\\&amp;quot;));&lt;br /&gt;            child.Rows.Add(AddTableRow(&amp;quot;&lt;/span&gt;Diagnostic File Name:&lt;span class="str"&gt;&amp;quot;, &amp;quot;&lt;/span&gt;txtFileName&lt;span class="str"&gt;&amp;quot;, 64, false, &amp;quot;&lt;/span&gt;LogFile.txt&lt;span class="str"&gt;&amp;quot;));&lt;br /&gt;&lt;br /&gt;            this.Controls.Add(child);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private TableRow AddTableRow(String labelText, String controlID, int maxLength, Boolean multiLine, string DefaultValue)&lt;br /&gt;        {&lt;br /&gt;            TableRow row = new TableRow();&lt;br /&gt;            TableCell labelCell = new TableCell();&lt;br /&gt;            TableCell controlCell = new TableCell();&lt;br /&gt;            Label olabel = new Label();&lt;br /&gt;            TextBox oText = new TextBox();&lt;br /&gt;            // Add the To:&lt;br /&gt;            olabel.Text = labelText;&lt;br /&gt;            olabel.CssClass = base.LabelCssClass;&lt;br /&gt;            labelCell.Controls.Add(olabel);&lt;br /&gt;            oText.ID = controlID;&lt;br /&gt;            oText.CssClass = base.TextBoxCssClass;&lt;br /&gt;            oText.Text = DefaultValue;&lt;br /&gt;            oText.MaxLength = maxLength;&lt;br /&gt;            if (multiLine)&lt;br /&gt;            {&lt;br /&gt;                oText.TextMode = TextBoxMode.MultiLine;&lt;br /&gt;                oText.Rows = System.Math.Min(6, (maxLength + 60) / 60);&lt;br /&gt;            }&lt;br /&gt;            controlCell.Controls.Add(oText);&lt;br /&gt;            row.Cells.Add(labelCell);&lt;br /&gt;            row.Cells.Add(controlCell);&lt;br /&gt;            return row;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void SetControlAccess(string controlID, Boolean readOnly)&lt;br /&gt;        {&lt;br /&gt;            TextBox oText = (TextBox)this.FindControl(controlID);&lt;br /&gt;            if (oText != null)&lt;br /&gt;                oText.ReadOnly = readOnly;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private string GetControlString(string controlID)&lt;br /&gt;        {&lt;br /&gt;            TextBox oText = (TextBox)this.FindControl(controlID);&lt;br /&gt;            if (oText != null)&lt;br /&gt;                return oText.Text;&lt;br /&gt;            else&lt;br /&gt;                return &amp;quot;&lt;/span&gt;[TextBox &lt;span class="str"&gt;'&amp;quot; + controlID + &amp;quot;'&lt;/span&gt; Not Found&lt;span class="str"&gt;&amp;quot;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void SetTextBoxValue(string controlID, string value)&lt;br /&gt;        {&lt;br /&gt;            TextBox oText = (TextBox)this.FindControl(controlID);&lt;br /&gt;            if (oText != null)&lt;br /&gt;                oText.Text = value;&lt;br /&gt;            else&lt;br /&gt;                oText.Text = &amp;quot;&lt;/span&gt;&lt;span class="str"&gt;&amp;quot;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;&lt;br /&gt;        #region Ensynch Event Log&lt;br /&gt;&lt;br /&gt;        private void SimpleLogFunction(string functionName, string Message, EventLogEntryType type, int eventID, short category)&lt;br /&gt;        {&lt;br /&gt;            using (StreamWriter mylog = new StreamWriter(@&amp;quot;&lt;/span&gt;C:\MyErrorLog.txt&lt;span class="str"&gt;&amp;quot;, true))&lt;br /&gt;            {&lt;br /&gt;                mylog.WriteLine(DateTime.Now.ToString(&amp;quot;&lt;/span&gt;yyyy-MM-dd hh:mm:ss&lt;span class="str"&gt;&amp;quot;) + &amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot; + functionName + &amp;quot;&lt;/span&gt;, &amp;quot; + Message);&lt;br /&gt;                mylog.Close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;       &lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We also need to add one more override method to our implementation, the CreateChildControls(), which will be called by the ILM interface to instruct our control to create its interface.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CreateChildControls()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.InitializeControls();&lt;br /&gt;                &lt;span class="kwrd"&gt;base&lt;/span&gt;.CreateChildControls();&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Activitites.CreateChildControls&amp;quot;&lt;/span&gt;, ex.Message, EventLogEntryType.Error, 1000, 100);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice I also have a call to my diagnostic SimpleLogFunction() here too. This version writes to &amp;quot;C:\MyErrorLog.txt&amp;quot; just in case I make a mistake somewhere. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;NOTE: Notice my extensive use of try-catch-finally blocks in my code. While these are not always the most efficient pieces of code, we are writing both a user interface and a workflow component and we don't want them to fail in production or we at least need them to fail gracefully. If you do any extensive SharePoint development you will also want to take this tack as all the interfaces with SharePoint are web service based and with the data being so dynamic requests can fail anywhere so you will want to trap them.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So let's go through each interface method and implement code on them one by one.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="158"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="234"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="158"&gt;CreateChildControls&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="234"&gt;This routine, as mentioned above places our controls into the design service for us. We build our utility functions to create our controls and place them within a table so we have a nicely laid out format.&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="158"&gt;GenerateActivityOnWorkflow&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="234"&gt;This method will be called by ILM when the user hits the save button and ILM wants us to return an instance of our EnsynchDiagnosticActivity activity with the properties in it filled in with the values entered from the text boxes in our user interface. The code is shown below&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; SequenceActivity GenerateActivityOnWorkflow(SequentialWorkflow workflow)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;GenerateActivityOnWorkflow&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Starting Activity Generation&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10000, 100);&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;this&lt;/span&gt;.ValidateInputs())&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;                EnSynch.Workflow.Activities.EnsynchDiagnosticActivity activity =&lt;br /&gt;                                                    &lt;span class="kwrd"&gt;new&lt;/span&gt; EnSynch.Workflow.Activities.EnsynchDiagnosticActivity();&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;GenerateActivityOnWorkflow&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Activity Created&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10000, 100);&lt;br /&gt;                activity.LogActivityName = GetControlString(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;);&lt;br /&gt;                activity.LogFolder = GetControlString(&lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;);&lt;br /&gt;                activity.LogFile = GetControlString(&lt;span class="str"&gt;&amp;quot;txtFileName&amp;quot;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;GenerateActivityOnWorkflow&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;Activity Properties Set&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10000, 100);&lt;br /&gt;               &lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; activity;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;GenerateActivityOnWorkflow Error&amp;quot;&lt;/span&gt;, ex.Message, EventLogEntryType.Error, 1000, 100);&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We create an instance of our activity, fill in the three properties we created (LogActivityName, LogFolder, and LogFile) by using a helper function, GetControlString() and then simply return it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The next several sections cover each interface in detail:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="152"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="247"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="152"&gt;LoadActivitySettings&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="247"&gt;This is called by ILM when it wants us to reload our user interface. It passes us a definition of our activity from its XAML definition. The code for LoadActivitySettings() is shown below&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadActivitySettings(SequenceActivity activity)&lt;br /&gt;        {&lt;br /&gt;            EnSynch.Workflow.Activities.EnsynchDiagnosticActivity activity2 =&lt;br /&gt;                        activity &lt;span class="kwrd"&gt;as&lt;/span&gt; EnSynch.Workflow.Activities.EnsynchDiagnosticActivity;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (activity2 != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;, activity2.IsDynamicActivity);&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;, activity2.LogFolder);&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtFileName&amp;quot;&lt;/span&gt;, activity2.LogFile);&lt;br /&gt;            }&lt;br /&gt;        } &lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="126"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="126"&gt;PersistSettings&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;Packages up the activity properties in an ActivitySettingsPartData collection and returns them to ILM for processing&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;         &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActivitySettingsPartData PersistSettings()&lt;br /&gt;        {&lt;br /&gt;            ActivitySettingsPartData data = &lt;span class="kwrd"&gt;new&lt;/span&gt; ActivitySettingsPartData();&lt;br /&gt;            data[&lt;span class="str"&gt;&amp;quot;LogActivityName&amp;quot;&lt;/span&gt;] = GetControlString(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;);&lt;br /&gt;            data[&lt;span class="str"&gt;&amp;quot;LogFolder&amp;quot;&lt;/span&gt;] = GetControlString(&lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;);&lt;br /&gt;            data[&lt;span class="str"&gt;&amp;quot;LogFile&amp;quot;&lt;/span&gt;] = GetControlString(&lt;span class="str"&gt;&amp;quot;txtFileName&amp;quot;&lt;/span&gt;);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; data;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="200"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="200"&gt;Description &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="200"&gt;RestoreSetting&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="200"&gt;Allows our interface to restore the values of our properties to the interface&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; RestoreSettings(ActivitySettingsPartData data)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (data != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;, data[&lt;span class="str"&gt;&amp;quot;LogActivityName&amp;quot;&lt;/span&gt;] &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;);&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;, data[&lt;span class="str"&gt;&amp;quot;LogFolder&amp;quot;&lt;/span&gt;] &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;);&lt;br /&gt;                SetTextBoxValue(&lt;span class="str"&gt;&amp;quot;txtFileName&amp;quot;&lt;/span&gt;, data[&lt;span class="str"&gt;&amp;quot;LogFile&amp;quot;&lt;/span&gt;] &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="115"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="284"&gt;Description &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="115"&gt;SwitchMode&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="284"&gt;This routine is called by ILM when it wants our control to switch from edit to view modes. Again, we make user of a helper function SetControlAccess() to set the access to read only in view mode.&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SwitchMode(ActivitySettingsPartMode mode)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;bool&lt;/span&gt; flag = mode != ActivitySettingsPartMode.Edit;&lt;br /&gt;            SetControlAccess(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;, flag);&lt;br /&gt;            SetControlAccess(&lt;span class="str"&gt;&amp;quot;txtFilePath&amp;quot;&lt;/span&gt;, flag);&lt;br /&gt;            SetControlAccess(&lt;span class="str"&gt;&amp;quot;txtFileName&amp;quot;&lt;/span&gt;, flag);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="90"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="309"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="90"&gt;Title&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="309"&gt;The title property provides the ILM interface with the title string that it will display for us on the design surface. &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;         &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Title&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Ensynch Diagnostic Activity&amp;quot;&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="400" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="110"&gt;Interface&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="289"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="110"&gt;ValidateInputs&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="289"&gt;ILM calls this method as the first step when a user presses the Save button on our activity on the design surface. In our case we are going to assume that the user always puts valid file and folder names. By the way, remember that since the target folder and file are going to be on the server any validation we do would be against that machine and not necessarily the client we are working on. &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So we are going to simply return &amp;quot;true&amp;quot; from this routine. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ValidateInputs()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So that's it. We have completed the coding for our activity. We can now build our library.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Building the library and loading it so that ILM will see it&lt;/h5&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So for ILM to make use of our custom activity, at least in Beta 3, the library will need to be signed and placed in the Global Assembly Cache (GAC) as well the _app_bin folder of the SharePoint application the ILM portal is installed into. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To install your library into the GAC you can simply copy the library into the C:\WINDOWS\assembly folder or you can use gacutil.exe to do that for you. See this reference: &lt;a href="http://support.microsoft.com/kb/315682"&gt;http://support.microsoft.com/kb/315682&lt;/a&gt; for complete instructions on signing and installing a library into the GAC.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In my case I am adding my control to an existing library that was already been created and signed. The illustration below shows the property sheet for the signing page of my library. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SP40AL8VTXI/AAAAAAAAAEQ/nLdzWuFwFpY/s1600-h/clip_image0033.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="147" alt="clip_image003" src="http://lh4.ggpht.com/pauldivaniii/SP40AeKY-BI/AAAAAAAAAEU/pzd2LwMPbm4/clip_image003_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The first time you install your library in the GAC you will want to grab the public key token and version information. We will need that in the next step. From the C:\Windows\assembly right click on your library and select Properties. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SP40Agj73cI/AAAAAAAAAEY/HZP21-CrwvY/s1600-h/clip_image0043.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="69" alt="clip_image004" src="http://lh6.ggpht.com/pauldivaniii/SP40A6xonoI/AAAAAAAAAEc/ExF6X2idfCw/clip_image004_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SP40BBNHdkI/AAAAAAAAAEg/M_OMvyLVo-c/s1600-h/clip_image0053.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="clip_image005" src="http://lh6.ggpht.com/pauldivaniii/SP40BYzmiHI/AAAAAAAAAEk/0eOt8W3m_2Q/clip_image005_thumb.png?imgmax=800" width="214" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So we are going to need the public key token: &amp;quot;6339eb144475917c&amp;quot; and the version: &amp;quot;1.0.0.0&amp;quot; for the next step.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Exposing our Activity to the ILM Process Designer&lt;/h5&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We are almost done. We need to copy our library to the _app_bin folder of our SharePoint web site. In my case this is in &amp;quot;C:\inetpub\wwwroot\wss\VirtualDirectories\80\_app_bin&amp;quot;. I am going to copy two files to this folder; my DLL and also the PDB file for my library which will allow me to attach to the SharePoint executable (w3wp.exe) to debug my code in the event there are some bugs to check out. When I get done my _app_bin folder will look like: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SP40Bti5i-I/AAAAAAAAAEo/PQmfAjc2zVc/s1600-h/clip_image0063.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="108" alt="clip_image006" src="http://lh6.ggpht.com/pauldivaniii/SP40CIsXEYI/AAAAAAAAAEs/jGYPwoPLOrw/clip_image006_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice this includes all of the ILM libraries as well.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;After installing our libraries we need to reset IIS and restart the ILM services in order for them to connect with our latest version of the library we just deployed. You can open a Command window on the SharePoint server and enter the: &amp;quot;iisreset&amp;quot; command and hit return. This will reset IIS. Next open the Services application from the Administrative Tools folder.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the Services application you will want to restart the ILM services. In the illustration below they are the first two services in the listing &amp;quot;Microsoft Identity Integration Server&amp;quot; and &amp;quot;Microsoft ILM Common Services&amp;quot;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SP40Ccc0QdI/AAAAAAAAAEw/5ZsODrVj75w/s1600-h/clip_image0073.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="74" alt="clip_image007" src="http://lh4.ggpht.com/pauldivaniii/SP40CiTjFaI/AAAAAAAAAE0/LJgCaSm64C8/clip_image007_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Figure 1‑20 - Services, ILM Services&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;NOTE: Every time you rebuild your library you will need to copy the new version to the GAC and to the _app_bin folder. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;One more step to go. We have to tell ILM about our custom activity. To do this we need to add our activity definition to the configuration file ILM uses for its Activity definitions: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Microsoft.IdentityManagement.Activities.arp&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The copy of &amp;#8220;Microsoft.IdentityManagement.Activities.arp&amp;#8221; we want to use is also located in the _app_bin folder of our SharePoint web site. There is a second copy located in the ILM folders in &amp;#8220;Program Files\Microsoft Identity Management&amp;#8221; which is not actually used by the portal.&lt;a href="file:///C:/Documents%20and%20Settings/pdivan/My%20Documents/Knowledge/ILM/Identity%20and%20Access%20Management%20Operations%20Guide%20-%20ILM%202%20Workflow%20Activity%20Walkthrough.docx#_ftn1"&gt;[1]&lt;/a&gt; Again, in my case this is in: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;quot;C:\inetpub\wwwroot\wss\VirtualDirectories\80\_app_bin&amp;quot; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The configuration entry for our new activity is shown below:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;IdentityManagementActivity&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;=&amp;quot;http://schemas.microsoft.com/IdentityManagement/v1&amp;quot;&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Assembly&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;EnsynchILMActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6339eb144475917c&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Assembly&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;TypeName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;EnSynch.ILM.Activities.EnsynchDiagnosticActivityUI&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;TypeName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ActivityName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;EnSynch.Workflow.Activities.EnsynchDiagnosticActivity&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ActivityName&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Ensynch Diagnostic Activity&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Ensynch ILM 2 Activity that writes Request data to a specified log file&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;PartImageSmall&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;/_layouts/images/approval_small.gif&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;PartImageSmall&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;PartImageLarge&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;/_layouts/images/approval_large.gif&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;PartImageLarge&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Categories&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Authentication&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Authorization&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Action&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Category&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Categories&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;IdentityManagementActivity&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The definition of all the fields is shown in the table below: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;table cellspacing="0" cellpadding="2" width="414" border="0"&gt;&lt;tbody&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;Element Name&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;Description&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;Assembly&amp;gt; &amp;lt;/Assembly&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;&lt;br /&gt;        &lt;p&gt;This is the date associated with the assembly that contains the custom activity. The contents should contain: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;Assembly name, Version, Culture, and the Public Key Token. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;Assembly Name: The assembly name is the name of the DLL minus the extension. In the example able the assembly DLL is named: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;Ensynch.IdentityManagement.Activities.dll. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;Version: The DLL version. In this example we are using version 1.0.0.0 &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;Culture: The culture the assembly was created for. In this case the assembly is neutral. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;        &lt;p&gt;PublicKeyToken: If you are putting your assembly into the GAC you will need to strongly type your assembly and copy it into the GAC. You can look at the properties once you have installed it there and access the public key token and the version.&lt;/p&gt;&lt;br /&gt;      &lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;TypeName&amp;gt; &amp;lt;/TypeName&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The full class name (including the namespace) of the class that provides the visual component in the Process Designer&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;ActivityName&amp;gt; &amp;lt;/ActivityName&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The full class name (including the namespace) of the workflow activity class that is associated with visual component.&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;Title&amp;gt;&amp;lt;/Title&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The title as you want it to appear in the designer&amp;#8217;s activity list&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;Description&amp;gt; &amp;lt;/Description&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The title as you want it to appear in the designer&amp;#8217;s activity list&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;PartImageSmall&amp;gt; &amp;lt;/PartImageSmall&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The URL to the small icon image file you want associated with your activity&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;PartImageLarge&amp;gt; &amp;lt;/PartImageLarge&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;The URL to the large icon image file you want associated with your activity&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;Categories&amp;gt; &amp;lt;/Categories&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;This the list of Process categories you designed or want your activity to appear in. Valid categories include: Authentication, Authorization and Action&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;    &lt;tr&gt;&lt;br /&gt;      &lt;td valign="top" width="139"&gt;&amp;lt;Category&amp;gt; &amp;lt;/Category&amp;gt;&lt;/td&gt;&lt;br /&gt;&lt;br /&gt;      &lt;td valign="top" width="273"&gt;Element for each action to include. Must be a child of &amp;lt;Caterories&amp;gt; element.&lt;/td&gt;&lt;br /&gt;    &lt;/tr&gt;&lt;br /&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So now let's bring up the portal and test out our new activity. In my example I am trying to monitor the progress of the workflow properties through the &amp;quot;AD Outbound Sync Process&amp;quot;, one of the processes that supports synchronizing various custom activities for an organization.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the Activities Tab of the Process editor we can see the process as it exists right now:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP40DCygNlI/AAAAAAAAAE4/Fii9L_Vthw0/s1600-h/clip_image0083.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="209" alt="clip_image008" src="http://lh4.ggpht.com/pauldivaniii/SP40De34p3I/AAAAAAAAAE8/ODPaUXDNyqQ/clip_image008_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I am going to select the &amp;quot;Add Activity&amp;quot; option on the bottom which brings up a list of activities for me to select from:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP40Dmb2_kI/AAAAAAAAAFA/ZvmZaIJY3ow/s1600-h/clip_image0093.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="clip_image009" src="http://lh3.ggpht.com/pauldivaniii/SP40D4wJNxI/AAAAAAAAAFE/J91Ml9oBXrM/clip_image009_thumb.png?imgmax=800" width="170" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;My activity is the one on the bottom. I select it and press Select. This brings up a copy of my activity in edit mode. Notice the three fields for setting our properties.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SP40EjYIjZI/AAAAAAAAAFI/iAj94z5O3DI/s1600-h/clip_image0103.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="106" alt="clip_image010" src="http://lh3.ggpht.com/pauldivaniii/SP40FJT0dqI/AAAAAAAAAFM/5V231BI3L4g/clip_image010_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I'm going to take the default folder and file name but I'm going to change the activity name to &amp;quot;After Login Name&amp;quot; and then save it and move it up just after the first activity.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SP40Fj_vqHI/AAAAAAAAAFQ/XN-jl1kDc2w/s1600-h/clip_image0113.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="60" alt="clip_image011" src="http://lh5.ggpht.com/pauldivaniii/SP40F1ej0cI/AAAAAAAAAFU/gmvLcY-9Zvk/clip_image011_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I'm going to do this after one more time and locate the second activity after the Password activity. My end result will look like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SP40GVlJd8I/AAAAAAAAAFY/tbVy0dpYLgM/s1600-h/clip_image0123.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="151" alt="clip_image012" src="http://lh5.ggpht.com/pauldivaniii/SP40GyRXnlI/AAAAAAAAAFc/A6--Xh1PCtA/clip_image012_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So this is nice but we can make a minor enhancement to our activity that will make it even better.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I'm going to change my Title property so that it includes the Activity Name we type in. My new code will look like this: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Title&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Ensynch Diagnostic Activity: &amp;quot;&lt;/span&gt; + GetControlString(&lt;span class="str"&gt;&amp;quot;txtActivityName&amp;quot;&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This makes my activity list look as shown below which makes the activity easier to understand. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP40HDu04uI/AAAAAAAAAFg/PZBldM2nrR0/s1600-h/clip_image0133.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="153" alt="clip_image013" src="http://lh3.ggpht.com/pauldivaniii/SP40HcITyHI/AAAAAAAAAFk/suL7C-xYGtk/clip_image013_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We press OK and then Submit and we are done with this step.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h5&gt;Testing out our Activity in Practice&lt;/h5&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we need to see if our activity works. Let's add a new user and see if we can follow the progress of the workflow in our log file.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the ILM Portal select &amp;quot;All Users&amp;quot; from the Quick Launch Bar and go to the &amp;quot;All Users&amp;quot; page.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP40HgKObBI/AAAAAAAAAFo/DSvWfq4mcoU/s1600-h/clip_image0143.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="209" alt="clip_image014" src="http://lh4.ggpht.com/pauldivaniii/SP40H33ep_I/AAAAAAAAAFs/q6JJo_xAUEg/clip_image014_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Pick the &amp;quot;New&amp;quot; user icon and create a new user. I am creating a full time employee named Adam Diagnostics as my test user. The next two shots show the data that I entered for Adam.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SP40IW2KmQI/AAAAAAAAAFw/uTzZ-QU6yuk/s1600-h/clip_image0153.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="207" alt="clip_image015" src="http://lh3.ggpht.com/pauldivaniii/SP40IwmNTvI/AAAAAAAAAF0/2vq5XtDlNzQ/clip_image015_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Figure 1‑28 - ILM Portal, Create User - Adam Diagnostic&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SP40JAiy0aI/AAAAAAAAAF4/sJ7Z5pljwRk/s1600-h/clip_image0163.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="212" alt="clip_image016" src="http://lh5.ggpht.com/pauldivaniii/SP40J7jzlJI/AAAAAAAAAF8/kJZPTXbLDHI/clip_image016_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Since I am done entering Adam's information I select the Finish button and then Submit from the summary screen.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Adam gets added to the list of users. The synchronization workflow will kick off at this point and run through all the activities in our process. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;When we look at the log file we created from our custom activity we see that it has recorded the information we were interested in:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Note: As of this writing we now know that the ARP file will be replaced in the release candidate and will be stored in the ILM database. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SP40KF_AVoI/AAAAAAAAAGA/ewkr8bDnN9k/s1600-h/clip_image0173.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="172" alt="clip_image017" src="http://lh4.ggpht.com/pauldivaniii/SP40KgLPGmI/AAAAAAAAAGE/KJ_g7ALqUxI/clip_image017_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So that's it. You have now created a custom activity for an ILM workflow.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4570237346466838189-8283064373358058366?l=makingdotnetwork.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MakingDotNetConceptsWork/~4/NqU1t11Km88" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://makingdotnetwork.blogspot.com/feeds/8283064373358058366/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4570237346466838189&amp;postID=8283064373358058366" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/8283064373358058366?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/8283064373358058366?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MakingDotNetConceptsWork/~3/NqU1t11Km88/how-to-create-custom-ilm-workflow.html" title="How to Create a Custom ILM Workflow Activity - Part III: Creating the Custom Workflow Activity UI" /><author><name>Paul Divan</name><uri>http://www.blogger.com/profile/03003052730236405176</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_Vs2hnSFhfYI/SPYglplUgKI/AAAAAAAAACI/EDWqHN3w408/S220/MugShot.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/pauldivaniii/SP4z-0FXg7I/AAAAAAAAAEE/LShlSvfL4fA/s72-c/clip_image001_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://makingdotnetwork.blogspot.com/2008/12/how-to-create-custom-ilm-workflow.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAMQ3g_fCp7ImA9WxRXFUw.&quot;"><id>tag:blogger.com,1999:blog-4570237346466838189.post-7116813944919360318</id><published>2008-10-20T07:43:00.001-07:00</published><updated>2008-10-20T07:43:02.644-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-20T07:43:02.644-07:00</app:edited><title>How to Create a Custom ILM Workflow Activity - Part II: Creating the Custom Workflow Activity</title><content type="html">&lt;p&gt;This is the second part of a three part series on creating a custom workflow activity for ILM 2.0. A reminder that in order to create and build this solution you will need an implementation of the ILM 2.0 Beta 3 server with a copy of Visual Studio 2008 Professional Developer edition installed on it. You can read the first entry here: &lt;a href="http://makingdotnetwork.blogspot.com/2008/10/how-to-create-custom-ilm-20-beta-3.html" target="_blank"&gt;How to Create a Custom ILM 2.0 Beta 3 Workflow Activity - Part I&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I want to again mention my two colleagues &lt;a href="http://www.identitychaos.com/"&gt;Brad Turner&lt;/a&gt; and &lt;a href="http://ILMBestPractices.com"&gt;David Lundell&lt;/a&gt; for their support and contributions to this effort as well as ILM itself. Both are ILM MVPs and their blogs are worth exploring whenever you have questions about ILM.&lt;/p&gt;  &lt;p&gt;In &lt;a href="http://makingdotnetwork.blogspot.com/2008/10/how-to-create-custom-ilm-20-beta-3.html" target="_blank"&gt;Part I&lt;/a&gt;, I laid out all the steps required to create the project and get it ready for developing the code. In Part II I will show you how the project develops to the point where we have the ILM compatible workflow foundation activity defined and in Part III I will show you how to add the UI class that allows the activity to be listed in the available activities in ILM Process Designer.&lt;/p&gt;  &lt;p&gt;Picking up from where we left off, create a new class file named: &lt;/p&gt;  &lt;p&gt;EnsynchDiagnosticActivity.cs&lt;/p&gt;  &lt;p&gt;Use the Activity template in the Workflow category as shown below. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPyYzr1m_iI/AAAAAAAAACg/er6wE3ZwpZ0/s1600-h/clip_image0013.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="clip_image001" src="http://lh4.ggpht.com/pauldivaniii/SPyY0EQHZ0I/AAAAAAAAACk/H_AjkWP_LhI/clip_image001_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;NOTE: You will probably have to add the ILM custom activities to your toolbox so right click on the toolbox and select &amp;quot;Add Tab&amp;quot; and add a new tab named &amp;quot;ILM Activities&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SPyY0kDZN7I/AAAAAAAAACo/sHJFR5CO1pk/s1600-h/clip_image0023.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="clip_image002" src="http://lh6.ggpht.com/pauldivaniii/SPyY1JoNJZI/AAAAAAAAACs/e7dqpzj5TnA/clip_image002_thumb.png?imgmax=800" width="136" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will end up with an empty new category:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SPyY1pmZ8-I/AAAAAAAAACw/E_scyJs5cR0/s1600-h/clip_image0033.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="200" alt="clip_image003" src="http://lh4.ggpht.com/pauldivaniii/SPyY107Q0zI/AAAAAAAAAC0/Zq9HG5b94lc/clip_image003_thumb.png?imgmax=800" width="220" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Right click in the ILM Activities space and select the &amp;quot;Choose Items &amp;#8230;&amp;quot; option.&lt;/p&gt;  &lt;p&gt;Select the &amp;quot;Browse&amp;#8230;&amp;quot; button and navigate to the _app_bin folder of your SharePoint web site and select the Microsoft.ResourceManagement.dll library. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPyY2J7QUcI/AAAAAAAAAC4/IcZe-9dG2OM/s1600-h/clip_image0043.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="192" alt="clip_image004" src="http://lh4.ggpht.com/pauldivaniii/SPyY3D0HYCI/AAAAAAAAAC8/4iyeaOkGkv4/clip_image004_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Press Open. If you sort the resulting list by Namespace you will see all the activities highlighted for this library. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SPyY3c0AWmI/AAAAAAAAADA/BTBVjF9Gd94/s1600-h/clip_image0053.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="170" alt="clip_image005" src="http://lh5.ggpht.com/pauldivaniii/SPyY4fdzpRI/AAAAAAAAADE/mLvR9-dz_UU/clip_image005_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Figure 1‑7 - Visual Studio, Toolbox Items&lt;/p&gt;  &lt;p&gt;Press OK and the activities will be added to your ILM Activities Toolbox.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SPyY4rf3GkI/AAAAAAAAADI/GZysT1hX0DM/s1600-h/clip_image0063.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="clip_image006" src="http://lh4.ggpht.com/pauldivaniii/SPyY5IlD-OI/AAAAAAAAADM/U-SF8g3hEEo/clip_image006_thumb.png?imgmax=800" width="106" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Drag a CurrentRequestActivity onto the design surface and rename the activity &amp;quot;LogRequestActivity&amp;quot;. Your activity should look like it does below:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SPyY5tD5YyI/AAAAAAAAADQ/SmKRAgpZkPo/s1600-h/clip_image0073.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="231" alt="clip_image007" src="http://lh6.ggpht.com/pauldivaniii/SPyY51myy6I/AAAAAAAAADU/WHdkaebMiAE/clip_image007_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Figure 1‑9 - Visual Studio, WF Designer&lt;/p&gt;  &lt;p&gt;Right click on the design surface and select View Code&lt;/p&gt;  &lt;p&gt;In the code we need to add the references to the ILM object model and also a reference to the collections object mode which many of the dictionary items are built from. And since we are potentially going to be working with some diagnostics level bits we add that along with System.IO since we&amp;#8217;re going to be writing to a file.&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.IdentityManagement.WebUI;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.ResourceManagement.Workflow.Activities;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.ResourceManagement.WebServices.WSResourceManagement;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.IdentityManagement.WebUI.Controls;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.ResourceManagement.Utilities;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.ObjectModel;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now we need to add a variable that will hold the data associated with the ILM request type. We'll call that currentRequest. For organizational purposes I like to isolate different sections of my code into regions. We'll locate this code in the &amp;quot;Activity Properties&amp;quot; region.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;public RequestType currentRequest;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now, because we are building a diagnostic activity we will want to write the diagnostics to a file in a folder of our choice. In addition we will want to provide a name that that will allow us to pinpoint where we have placed a copy of this activity in our workflow. So we need three additional properties that we will create in the user interface component of this activity. We create these as dependency properties, which will allow the ILM design surface to set the properties of the activity and have them persist into the workflow definition. These properties actually show up as attributes of the activity definition in the XOML workflow definition we will create in the ILM portal using our activity.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So we create three properties, LogActivityName, LogFolder and LogFile:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DependencyProperty LogActivityNameProperty =&lt;br /&gt;                    DependencyProperty.Register(&lt;span class="str"&gt;&amp;quot;LogActivityName&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EnsynchDiagnosticActivity));&lt;br /&gt; &lt;br /&gt;        [Browsable(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;br /&gt;        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]&lt;br /&gt;        [Category(&lt;span class="str"&gt;&amp;quot;Properties&amp;quot;&lt;/span&gt;)]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LogActivityName&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;.GetValue(EnsynchDiagnosticActivity.LogActivityNameProperty); }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetValue(EnsynchDiagnosticActivity.LogActivityNameProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DependencyProperty LogFolderProperty =&lt;br /&gt;                    DependencyProperty.Register(&lt;span class="str"&gt;&amp;quot;LogFolder&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EnsynchDiagnosticActivity));&lt;br /&gt; &lt;br /&gt;        [Browsable(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;br /&gt;        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]&lt;br /&gt;        [Category(&lt;span class="str"&gt;&amp;quot;Properties&amp;quot;&lt;/span&gt;)]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LogFolder&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;.GetValue(EnsynchDiagnosticActivity.LogFolderProperty); }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetValue(EnsynchDiagnosticActivity.LogFolderProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt; &lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; DependencyProperty LogFileProperty =&lt;br /&gt;                    DependencyProperty.Register(&lt;span class="str"&gt;&amp;quot;LogFile&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(EnsynchDiagnosticActivity));&lt;br /&gt; &lt;br /&gt;        [Browsable(&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;br /&gt;        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]&lt;br /&gt;        [Category(&lt;span class="str"&gt;&amp;quot;Properties&amp;quot;&lt;/span&gt;)]&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LogFile&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;)&lt;span class="kwrd"&gt;this&lt;/span&gt;.GetValue(EnsynchDiagnosticActivity.LogFileProperty); }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SetValue(EnsynchDiagnosticActivity.LogFileProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now let's go back to the design surface. We need to connect the CurrentRequestActivity we placed into our activity to the currentRequest parameter we created.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SPyY6F8e8TI/AAAAAAAAADY/LAENUbKZDoc/s1600-h/clip_image0083.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="124" alt="clip_image008" src="http://lh5.ggpht.com/pauldivaniii/SPyY6cVbTJI/AAAAAAAAADc/YNZnGyx0NzI/clip_image008_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Pick the ellipses to the right of the CurrentRequest property.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPyY6hWm40I/AAAAAAAAADg/ju7C9Ofu9k0/s1600-h/clip_image0093.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="197" alt="clip_image009" src="http://lh4.ggpht.com/pauldivaniii/SPyY7e8eXyI/AAAAAAAAADk/BnKUlrF5PtA/clip_image009_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Select the currentRequest (this is the variable we created in the code) and select OK. If you open up the CurrentRequest property now it will show how it is connected to our code. A little side note here: we could have selected the &amp;#8220;Bind to a new member&amp;#8221; tab and created the &amp;#8220;currentRequest&amp;#8221; parameter right from here instead of manually coding it in as we did above. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SPyY78TD02I/AAAAAAAAADo/aDpU0gsFjdQ/s1600-h/clip_image0103.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="149" alt="clip_image010" src="http://lh4.ggpht.com/pauldivaniii/SPyY8LkzL0I/AAAAAAAAADs/65KpGo67E8w/clip_image010_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Save this and then go back to the code. Let's take a quick look at the SequenceActivity that our activity is built from. Right click on the SequenceActivity interface and select &amp;quot;Go To Definition&amp;quot;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPyY8coH2BI/AAAAAAAAADw/S4i9lfOnqG4/s1600-h/clip_image0113.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="132" alt="clip_image011" src="http://lh6.ggpht.com/pauldivaniii/SPyY8lJHHtI/AAAAAAAAAD0/pBNPKWgNeM4/clip_image011_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Figure 1‑13 &amp;#8211;Selecting the &amp;#8220;Go To Definition&amp;#8221; option on the SequenceActivity class&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;NOTE: You should see the following definition:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPyY9LNABCI/AAAAAAAAAD4/kJy0jqfj2Mo/s1600-h/clip_image0123.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="89" alt="clip_image012" src="http://lh5.ggpht.com/pauldivaniii/SPyY9WUDMFI/AAAAAAAAAD8/ZPVVxzac8Go/clip_image012_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Figure 1‑14 &amp;#8211;Summary view of the SequenceActivity Class Definition&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;For our purposes we are going to implement an override of the OnSequenceComplete event handler and the HandleFault event handler in case we run into a problem.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So now back to our code. I'm going to paste in the code I am going use for these two events which looks like what you are seeing below. In the &amp;#8220;OnSequenceComplete&amp;#8221; method I am writing out the object type and the request type as well as cycling through the request parameters and workflows dictionary to write those out as well. For the object type and request type I am using a couple of helper functions that we&amp;#8217;ll insert a little further down.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="preproc"&gt;#region&lt;/span&gt; Event Processing&lt;br /&gt;        &lt;br /&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnSequenceComplete(ActivityExecutionContext executionContext)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                SequentialWorkflow containingWorkflow = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!SequentialWorkflow.TryGetContainingWorkflow(&lt;span class="kwrd"&gt;this&lt;/span&gt;, &lt;span class="kwrd"&gt;out&lt;/span&gt; containingWorkflow))&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; InvalidOperationException(&lt;span class="str"&gt;&amp;quot;Unable to get Containing Workflow&amp;quot;&lt;/span&gt;);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// Output the Request type and object type&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Request Object Type    = \&amp;quot;&amp;quot;&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetObjectType() + &lt;span class="str"&gt;&amp;quot;\&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Request Operation Type = \&amp;quot;&amp;quot;&lt;/span&gt; + &lt;span class="kwrd"&gt;this&lt;/span&gt;.GetOperation() + &lt;span class="str"&gt;&amp;quot;\&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt;                &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// UpdateRequestParameter derives from CreateRequestParameter.  Since we only need PropertyName / value pairs,&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// simplify the code to work on CreateRequestParameter only.&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;                ReadOnlyCollection&amp;lt;CreateRequestParameter&amp;gt; requestParameters = &lt;span class="kwrd"&gt;this&lt;/span&gt;.currentRequest.ParseParameters&amp;lt;CreateRequestParameter&amp;gt;();&lt;br /&gt;                &lt;span class="rem"&gt;//&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// Traverse CreateRequestParameters in and print out each attribute in the request&lt;/span&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// &lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Cycle Through the Request Parameters&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt; &lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (CreateRequestParameter requestParameter &lt;span class="kwrd"&gt;in&lt;/span&gt; requestParameters)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;RequestParameter (\&amp;quot;&amp;quot;&lt;/span&gt; + requestParameter.PropertyName + &lt;span class="str"&gt;&amp;quot;\&amp;quot;)&amp;quot;&lt;/span&gt;,&lt;br /&gt;                                           &lt;span class="str"&gt;&amp;quot; = \&amp;quot;&amp;quot;&lt;/span&gt; + requestParameter.Value.ToString() + &lt;span class="str"&gt;&amp;quot;\&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt;                }&lt;br /&gt; &lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Cycle Through the Workflow Dictionary&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt; &lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (KeyValuePair&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; dItem &lt;span class="kwrd"&gt;in&lt;/span&gt; containingWorkflow.WorkflowDictionary)&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Dictionary Entry (\&amp;quot;&amp;quot;&lt;/span&gt; + dItem.Key + &lt;span class="str"&gt;&amp;quot;\&amp;quot;)&amp;quot;&lt;/span&gt;,&lt;br /&gt;                                           &lt;span class="str"&gt;&amp;quot; = \&amp;quot;&amp;quot;&lt;/span&gt; + dItem.Value.ToString() + &lt;span class="str"&gt;&amp;quot;\&amp;quot;&amp;quot;&lt;/span&gt;, EventLogEntryType.Information, 10002, 100);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;this&lt;/span&gt;.SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;Diagnostic Log Entry Request Exception&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot; = '&amp;quot;&lt;/span&gt; + ex.Message + &lt;span class="str"&gt;&amp;quot;'&amp;quot;&lt;/span&gt;, EventLogEntryType.Error, 10005, 100);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;base&lt;/span&gt;.OnSequenceComplete(executionContext);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)&lt;br /&gt;        {&lt;br /&gt;            SimpleLogFunction(&lt;span class="str"&gt;&amp;quot;HandleFault&amp;quot;&lt;/span&gt;, exception.Message, EventLogEntryType.Error, 1000, 100);&lt;br /&gt; &lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ActivityExecutionStatus.Closed;&lt;br /&gt;}&lt;br /&gt;&lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice I keep calling a function named SimpleLogFunction. So we need to add one additional section, the Utility Function region that holds that routine. Here I simply (hence the name) create/open the file in the folder specified and append a record containing the specified entry to the file. This is also where we add our two helper functions to output the request type and object type.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="preproc"&gt;#region&lt;/span&gt; Utility Functions&lt;br /&gt; &lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SimpleLogFunction(&lt;span class="kwrd"&gt;string&lt;/span&gt; functionName, &lt;span class="kwrd"&gt;string&lt;/span&gt; Message, EventLogEntryType type, &lt;span class="kwrd"&gt;int&lt;/span&gt; eventID, &lt;span class="kwrd"&gt;short&lt;/span&gt; category)&lt;br /&gt;     {&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; delim = &lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;          &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamWriter mylog = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(Path.Combine(&lt;span class="kwrd"&gt;this&lt;/span&gt;.LogFolder, &lt;span class="kwrd"&gt;this&lt;/span&gt;.LogFile), &lt;span class="kwrd"&gt;true&lt;/span&gt;))&lt;br /&gt;          {&lt;br /&gt;              mylog.WriteLine(DateTime.Now.ToString(&lt;span class="str"&gt;&amp;quot;yyyy-MM-dd hh:mm:ss&amp;quot;&lt;/span&gt;) + &lt;span class="str"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; + &lt;br /&gt;                              &lt;span class="kwrd"&gt;this&lt;/span&gt;.LogActivityName + &lt;span class="str"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; + &lt;br /&gt;                              functionName + &lt;span class="str"&gt;&amp;quot;, &amp;quot;&lt;/span&gt; + Message);&lt;br /&gt;              mylog.Close();&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt; &lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetOperation()&lt;br /&gt;   {&lt;br /&gt;            &lt;span class="kwrd"&gt;switch&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.currentRequest.Operation)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Create:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Create&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Delete:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Delete&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Enumerate:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Enumerate&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Get:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Get&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Pull:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Pull&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.Put:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Put&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; OperationType.SystemEvent:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;System Event&amp;quot;&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;default&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;&amp;quot;Unknown Operation&amp;quot;&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetObjectType()&lt;br /&gt;    {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; currentRequest.TargetObjectType;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;&lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt;	font-size: small;&lt;br /&gt;	color: black;&lt;br /&gt;	font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt;	background-color: #ffffff;&lt;br /&gt;	/*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt;	background-color: #f4f4f4;&lt;br /&gt;	width: 100%;&lt;br /&gt;	margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So that's it for creating the workflow activity itself. Let's stop and build this solution just to make sure we did everything correctly.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the third and last post in this series, we'll create the ILM UI class that pulls the whole solution together and allows us to end up with a custom workflow activity that we can see in the ILM Process Manager Design Surface. Stay Tuned.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4570237346466838189-7116813944919360318?l=makingdotnetwork.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MakingDotNetConceptsWork/~4/pBAj4ocYfLs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://makingdotnetwork.blogspot.com/feeds/7116813944919360318/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4570237346466838189&amp;postID=7116813944919360318" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/7116813944919360318?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/7116813944919360318?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MakingDotNetConceptsWork/~3/pBAj4ocYfLs/how-to-create-custom-ilm-workflow.html" title="How to Create a Custom ILM Workflow Activity - Part II: Creating the Custom Workflow Activity" /><author><name>Paul Divan</name><uri>http://www.blogger.com/profile/03003052730236405176</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_Vs2hnSFhfYI/SPYglplUgKI/AAAAAAAAACI/EDWqHN3w408/S220/MugShot.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/pauldivaniii/SPyY0EQHZ0I/AAAAAAAAACk/H_AjkWP_LhI/s72-c/clip_image001_thumb.png?imgmax=800" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://makingdotnetwork.blogspot.com/2008/10/how-to-create-custom-ilm-workflow.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ACRXwzcSp7ImA9WxRXEEQ.&quot;"><id>tag:blogger.com,1999:blog-4570237346466838189.post-7189578748371823225</id><published>2008-10-15T09:44:00.001-07:00</published><updated>2008-10-15T10:29:24.289-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-15T10:29:24.289-07:00</app:edited><title>How to Create a Custom ILM 2.0 Beta 3 Workflow Activity - Part I</title><content type="html">&lt;p&gt;As my colleagues and I at Ensynch, specifically &lt;a href="http://www.identitychaos.com"&gt;Brad Turner&lt;/a&gt; and &lt;a href="http://ILMBestPractices.com"&gt;David Lundell&lt;/a&gt;, were digging into ILM 2.0 Beta 3, the power of the new Processing features that are built into this new version took us on a wonder journey that started generating ideas about how we could use this to facilitate all sorts of cool add-ons that you would potentially want to have happen when a part or all of a person's identity changed.&lt;/p&gt;  &lt;p&gt;I mean, when a new employee was added could we add a custom activity to the ILM library of activities that would calculate a unique user name? Could we create an activity that would allow us to easily integrate with an external system and be easily configured to access that system and return some key data value or values that we could add to the request stream. Could we then make use of that data in the action step to fill in extended properties in the target object of the request that represented that external system? &lt;/p&gt;  &lt;p&gt;We thought, &amp;quot;we have to learn how to make this work&amp;quot;. So, in my first set of blogs, &lt;strong&gt;ever&lt;/strong&gt;, I am going to layout the basic steps to create a custom ILM workflow activity. I'm going to lay this out from the perspective of an Infrastructure Engineer who has done some dabbling into code with Visual Studio but who does not make a career out of developing but would rather spend their time coordinating and configuring ILM for their customers and companies.&lt;/p&gt;  &lt;p&gt;What's nice about this activity is that it posts diagnostic records out to a log file, of your own choosing, which prints out all the parameters of the workflow, the request object and the target object. You can insert this activity before and after any activity in your ILM Process in order to track what is happening to these parameters as your workflow runs. This can help ILM administrators create and debug Process Flows without the need to writing custom code to analyze problems they might encounter along the way.&lt;/p&gt;  &lt;p&gt;In fact we don't actually get to the code until second post so bear with me and all will be revealed over the next couple of weeks. &lt;/p&gt;  &lt;p&gt;To create the custom activity we have designed here you will need an implementation of the ILM 2.0 Beta 3 server with a copy of Visual Studio 2008 Professional Developer edition installed. You will be working directly on the SharePoint server that the ILM portal has been installed on. In Beta 3.0 the installations have all the ILM components installed on the same server or virtual machine. For the Beta 3 release the library we are going to create will have to be installed both in the Global Assembly Cache (GAC) as well as the _app_bin folder of the ILM SharePoint Portal. These instructions may change for the Release Candidate (RC) but for now the need to copy the library to both locations is a requirement. &lt;/p&gt;  &lt;p&gt;By the way I will be creating this example in C# but the code is easily translatable unto VB.&lt;/p&gt;  &lt;h5&gt;Creating the Visual Studio Project&lt;/h5&gt;  &lt;p&gt;The first step in this process is to create a Workflow Activity library as shown in the figure below. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPYd0yd7xPI/AAAAAAAAABE/25ulkjMZxCE/s1600-h/clip_image0013.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="168" alt="clip_image001" src="http://lh4.ggpht.com/pauldivaniii/SPYd1hpbUNI/AAAAAAAAABM/vSE8hiLudDU/clip_image001_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Figure 1‑1 - Creating WF Project&lt;/p&gt;  &lt;p&gt;Once the project is opened we want to preset a few things. We want to set the default namespace to something more meaningful than out project name. In my case I am going to be using two namespaces, one for the workflow activity (EnSynch.Workflow.Activities) and another for the user interface component of the activity (EnSynch.ILM.Activities).&lt;/p&gt;  &lt;p&gt;In the Solutions Explorer Right click on the EnsynchCustomActivities project and select &amp;quot;Properties&amp;quot;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/pauldivaniii/SPYd2LuMP6I/AAAAAAAAABQ/ZzDvsBPF8hQ/s1600-h/clip_image0023.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="179" alt="clip_image002" src="http://lh5.ggpht.com/pauldivaniii/SPYd2R_VPnI/AAAAAAAAABU/4hdI-lPfWL4/clip_image002_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Figure 1‑2 - Visual Studio, changing default namespace&lt;/p&gt;  &lt;p&gt;Change the name of the &amp;quot;Default namespace&amp;quot; field to &amp;quot;Ensynch.Workflow.Activities&amp;quot;. Save this configuration and close the property sheet; &lt;/p&gt;  &lt;p&gt;Now select the Signing tab on the left side. Since we are going to have to place our library into the Global Assembly Cache (GAC) we need to have a signed library.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/pauldivaniii/SPYd3Kd1YhI/AAAAAAAAABY/Q_xABrR8N5g/s1600-h/clip_image0033.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="158" alt="clip_image003" src="http://lh5.ggpht.com/pauldivaniii/SPYd3sDslWI/AAAAAAAAABc/rDiHzQcmAfs/clip_image003_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Check the &amp;quot;Sign the assembly&amp;quot; checkbox and select the &amp;lt;New&amp;#8230;&amp;gt; option from the dropdown list. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SPYd30aM-xI/AAAAAAAAABg/gAWyRkZ3_eY/s1600-h/clip_image0043.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="57" alt="clip_image004" src="http://lh6.ggpht.com/pauldivaniii/SPYd4OLTrEI/AAAAAAAAABk/Y-p7UIFHTCc/clip_image004_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In the Create Strong Name Key dialog box enter a name for your key file (in my case I entered Ensynch.snk) uncheck the &amp;quot;Protect my key file with a password&amp;quot; checkbox and press OK.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/pauldivaniii/SPYd4drqlsI/AAAAAAAAABo/bLyr8lAAlzo/s1600-h/clip_image0053.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="154" alt="clip_image005" src="http://lh4.ggpht.com/pauldivaniii/SPYd4hGngpI/AAAAAAAAABs/_OsFwhyYF9U/clip_image005_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Do a Save All on your project and close the properties window.&lt;/p&gt;  &lt;p&gt;We need to add the ILM libraries as references to our project. In the solutions explorer, right click on the References folder and select &amp;#8220;Add Reference&amp;#8221;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPYd4-rvpyI/AAAAAAAAABw/Pu1dnrZGF5U/s1600-h/clip_image0063.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="205" alt="clip_image006" src="http://lh4.ggpht.com/pauldivaniii/SPYd5HrJ78I/AAAAAAAAAB0/tlSHgL4mHKM/clip_image006_thumb.png?imgmax=800" width="244" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Select the Browse tab.&lt;/p&gt;  &lt;p&gt;Browse to the _app_bin folder of your SharePoint. Select all the ILM libraries as shown in the figure below. Press OK&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/pauldivaniii/SPYd5ZixqzI/AAAAAAAAAB4/Oo2RIad8IBU/s1600-h/clip_image0073.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="244" alt="clip_image007" src="http://lh3.ggpht.com/pauldivaniii/SPYd53DFEWI/AAAAAAAAAB8/bFW_KQq_K0w/clip_image007_thumb.png?imgmax=800" width="222" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Do a Save All on your project.&lt;/p&gt;  &lt;p&gt;You can delete the Activity1.cs file.&lt;/p&gt;  &lt;p&gt;So that's it for this entry in Part II I'll show you how to create the custom workflow activity and then in Part III we'll create the ILM user interface class and install and configure the completed assembly up to ILM.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4570237346466838189-7189578748371823225?l=makingdotnetwork.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MakingDotNetConceptsWork/~4/AG7G0VkvJDA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://makingdotnetwork.blogspot.com/feeds/7189578748371823225/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=4570237346466838189&amp;postID=7189578748371823225" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/7189578748371823225?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4570237346466838189/posts/default/7189578748371823225?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MakingDotNetConceptsWork/~3/AG7G0VkvJDA/how-to-create-custom-ilm-20-beta-3.html" title="How to Create a Custom ILM 2.0 Beta 3 Workflow Activity - Part I" /><author><name>Paul Divan</name><uri>http://www.blogger.com/profile/03003052730236405176</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_Vs2hnSFhfYI/SPYglplUgKI/AAAAAAAAACI/EDWqHN3w408/S220/MugShot.JPG" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/pauldivaniii/SPYd1hpbUNI/AAAAAAAAABM/vSE8hiLudDU/s72-c/clip_image001_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://makingdotnetwork.blogspot.com/2008/10/how-to-create-custom-ilm-20-beta-3.html</feedburner:origLink></entry></feed>

