Posts Mentioning RSS Toggle Comment Threads | Keyboard Shortcuts

  • Chewy Chong 6:27 am on April 12, 2006 Permalink | Reply  

    Adventures with Windows Workflow – Hosting a Workflow with Tracing and Persistence 

    The great thing about my job is being able to work with cutting edge / brand spanking new technologies that still have the “new car smell”.  The one I’m currently working with is Windows Workflow. 

     

    I have been doing a lot of presentations on this topic recently and some of the key features I discuss is WF’s built-in capabilities for tracking and persistence. 

     

    -          Workflow tracking:  The ability to look inside an executing or executed workflow and see what is happening.  This is a key feature for workflow reporting and troubleshooting.

    -          Workflow persistence:  When a workflow is executing… it occupies CPU and memory.  If the workflow is long running (hours, days, years)… you don’t want it to continually occupy CPU and RAM.  Persistence allows the workflow instance to be saved (aka “persisted”) to something (eg file, SQL, toilet paper roll) for resumption at a later time.  

     

    These are key features of any workflow engine.  Hmm… this begs the next question… “How do I use / enable these features”?

     

    Windows Workflow’s full name is Windows Workflow Foundation (WF for short).  All the current emphasis has been on “Workflow” and not “Foundation”.  WF is not a server product.  Instead, it is a foundation that provides workflow functionality that can be consumed by your existing / new apps.  As to how it is consumed… it is up to you (build your own server or integrate into your existing app or whatever else you can think of).

     

    So the first point is … you need to create something that will host the workflow.  In my demos, a simple command line app acts as my host:

     

    1.      Create the workflow runtime (WorkflowRuntime)

    2.      Create an instance of the workflow in question and start execution

     

    When you create a “Sequential / State Machine Workflow Console Application” workflow project, it auto-generates all this code in the command line app for you. 

     

    You’ll notice some code about delegates… this just tells the command line app to stick around until the workflow runtime is complete.  The runtime is asynchronous so without the delegates, after you kick up the workflowruntime… the command line app will finish and shutdown thereby killing the still executing workflow runtime.

     

    OK.  That’s great but how do you enable tracking or persistence?  You do this by specifying tracking and persistence parameters when you instantiate the workflow runtime.  The rough process looks like:

     

    1.      Create the workflow runtime (WorkflowRuntime)

    2.      Set up tracking for the runtime

    3.      Set up persistence for the runtime

    4.      Create an instance of the workflow in question and start execution

     

    I wrote a simple to use host that demonstrates how you to enable tracking and persistence.  Here it is:

     

    static void Main(string[] args)

    {

        // You need to reference the foll
    owing namespaces for this method

        //      using System.Workflow.Runtime;

        //      using System.Workflow.Runtime.Tracking;

        //      using System.Threading;

     

     

        // — Configure this FIRST ————————     

        Type workflowType = typeof(WorkflowProject1.TestWF1);

     

        bool enableTracking = true;

        string sqlTrackingDbConnString = “Initial Catalog=Tracking;Data Source=localhost;Integrated Security=SSPI;”;

     

        bool enablePersistence = true;

        string sqlPersistenceDbConnString = “Initial Catalog=Persistence;Data Source=localhost;Integrated Security=SSPI;”;

        // ————————————————

     

        // Crank up a runtime

        WorkflowRuntime workflowRuntime = new WorkflowRuntime();

     

        // Add Tracking abilities

        if (enableTracking)

        {

            workflowRuntime.AddService(new SqlTrackingService(sqlTrackingDbConnString));

        }

     

        // Add Persistence abilities

        if (enablePersistence)

        {

      
         
    workflowRuntime.AddService(new SqlWorkflowPersistenceService(sqlPersistenceDbConnString, true, new TimeSpan(0, 0, 30), new TimeSpan(0, 2, 0)));

        }

     

        // Some other magic

        AutoResetEvent waitHandle = new AutoResetEvent(false);

        workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); };

        workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)

        {

            Console.WriteLine(e.Exception.Message);

            waitHandle.Set();

        };

     

        // Create an instance of the workflow and start it up

        WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowType);

        instance.Start();

     

     

        // Clean up

        waitHandle.WaitOne();

    }

    Take note that in my example, you need to specify a SQL database for tracking and one for persistence.  The Windows Workflow SDK provides .sql scripts that will create the tables and stored procs.  You just need to create a DB then run the two scripts.

     

    For Tracking:

     

    C:\WINDOWS\WinFX\v3.0\Windows Workflow Foundation\SQL\EN

     

    Tracking_Schema.sql

    Tracking_Logic.sql

     

    For Persistence:

     

    C:\WINDOWS\WinFX\v3.0\Windows Workflow Foundation\SQL\EN

     

    SqlPersistenceService_Schema.sql

    SqlPersistenceService_Logic.sql

     

    More details on tracking can be found:

     

    http://blogs.msdn.com/moustafa/archive/2006/03/15/552184.aspx

    (there is an error with the “enable track” C# code… should be a space between the words data source)

     

    http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/en-us/wf_samples/html/4f70c1c5-f82d-4d5f-8b7d-943b9f99f8e2.asp

    (explains how the sample
    works and what the UpdateV1DefaultTrackingProfile.sql file does)

     

    More details on persistence can be found:

     

    http://weblogs.asp.net/gsusx/archive/2005/10/05/426699.aspx

     

     

     

     
  • Chewy Chong 5:34 am on April 12, 2006 Permalink | Reply  

    Outlook Macro to Move an Email to Folder 

    When I took on my new job recently (about 3 months ago), I had no idea how much email I would be getting.  Needless to say… keeping my head above the “email water” has been consuming every free moment I have.  Be it on the airplane or during the weekend when the misses is still asleep.  

     

    The good news is… I’m getting better and have put together a (debatably) decent email management system.  The center of it is moving an email from my inbox to subfolders with marcos and shortcut keys.

     

    Here is a copy of the macro I put together that’ll move the selected email item to a sub-folder.  For each subfolder you want to move to… you need to create another macro.  After you have tested the macro… add it to the tool bar and mark it with a shortcut key.  Then, you can simply keyboard your way through your emails moving them one by one to a “for action” folder or “for review” folder.

     

    Sub MoveSelectedMessagesToFolder()

    On Error Resume Next

     

     

        Dim objFolder As Outlook.MAPIFolder, objInbox As Outlook.MAPIFolder

        Dim objNS As Outlook.NameSpace, objItem As Outlook.MailItem

     

     

        Set objNS = Application.GetNamespace(“MAPI”)

        Set objInbox = objNS.GetDefaultFolder(olFolderInbox)

        Set objFolder = objInbox.Folders(“_Reviewed“)

    ‘Assume this is a mail folder

     

     

        If objFolder Is Nothing Then

            MsgBox “This folder doesn’t exist!”, vbOKOnly + vbExclamation, “INVALID FOLDER”

        End If

     

     

        If Application.ActiveExplorer.Selection.Count = 0 Then

            ‘Require that this procedure be called only when a message is selected

            Exit Sub

        End If

     

     

        For Each objItem In Application.ActiveExplorer.Selection

            If objFolder.DefaultItemType = olMailItem Then

                If objItem.Class = olMail Then

                    objItem.Move objFolder

                End If

            End If

        Next

     

     

        Set objItem = Nothing

        Set objFolder = Nothing

        Set objInbox = Nothing

        Set objNS = Nothing

    End Sub

     

     
    • http:// 4:50 pm on November 8, 2007 Permalink | Reply

      Chewy:Great little piece of code – very helpful and almost exactly what I was looking for however I have a problem:Q: I’m running on an exchange server so my Inbox is not local. The code as written directs all mail to a specified folder under the primary inbox folder (in your code it was “_Reviewed”). How do I change the macro to move the message to an archive folder under my “Personal Folders” which are stored on my local drive?Set objFolder = objInbox.Folders(“_Reviewed”)Any insight (or better yet an example of code) would be much appreciated.Thanks.

    • http:// 6:50 pm on March 24, 2008 Permalink | Reply

      This is an AWESOME macro. One question though. I access Gmail via IMAP in Outlook 2007. Then I have loaded all of my other POP accounts into Gmail and set-up a label that labels each message when it comes in based on the account it comes in through. This effectively turns all of my POP e-mail accounts into IMAP accounts.This does two great things for me: allows me to “file” mail via Gmail’s web-based interface and not have to file it again when I get back to my computer (like I would have to do with most POP-based accounts with web access) and it allows me to “file” mail via Gmail’s mobile application on my Blackberry (unless you are using the Blackberry Enterprise Server for Outlook–which I am not–the current Blackberry mail system does not allow you to file mail from the device). So both of those save me a TON of time. I can be sitting in a cab and reading/filing messages and then get back to my desk and not have to deal with them a second time.So, here’s my question. This macro ROCKS, but is there a way to tell it to file the message into the “All Mail” folder in the “Gmail” PST rather than the “Archive” folder in the “Personal Folders” PST?If anyone can figure that out, you are awesome!

    • http:// 2:58 am on July 31, 2008 Permalink | Reply

      We’ve got about 1000 users that currently have their Auto Archive folder set to their profile location and we need to move it to a mapped drive on M:\ArchiveMail.pst. Is this possible through a Macro that could run at Outlook start up?Thanks,Bill

    • CAMURPHY 2:56 pm on October 2, 2008 Permalink | Reply

      RE: Moving to Personal Folders…Replacing:Set objFolder = objInbox.Folders(“_Reviewed”)withSet objFolder = objNS.Folders.Item(“Personal Folders”).Folders.Item(“Archive”).Folders.Item(“2008″)works for me. Assuming you wish to push the mail into “Personal Folders -> Archive -> 2008″HTH

    • CAMURPHY 2:56 pm on October 2, 2008 Permalink | Reply

      RE: Moving to Personal Folders…Replacing:Set objFolder = objInbox.Folders(“_Reviewed”)withSet objFolder = objNS.Folders.Item(“Personal Folders”).Folders.Item(“Archive”).Folders.Item(“2008″)works for me. Assuming you wish to push the mail into “Personal Folders -> Archive -> 2008″HTH

    • steve_B 5:44 pm on October 28, 2008 Permalink | Reply

      I am trying out this macro in office 2007 and have noticed that when I use my nifty buttons the time and date stamps of the messages are not preserved. Also, when opening the message it opens as a message that “has not yet been sent.” Is there a way to have the macro use Outlook’s built in “move to a folder” function or another way to preserve this information?

    • http:// 1:45 am on May 12, 2009 Permalink | Reply

      Hello, I am using your code it works fantastic. I have been trying to utilize it on a microsoft exchange mailbox that is NOT the default mailbox and I can not get it to work… I think the problem is with the following code: Set objNS = Application.GetNamespace(“MAPI”) Set objInbox = objNS.GetDefaultFolder (olFolderInbox)The name of the mailbox I need to move the message from is “Mailbox – Phoenix, CPC” (FYI: this is not the default mailbox) Set objFolder = objInbox.Folders(“_Inbox to be worked”)I can get the message to move from the above mailbox, but it will only move to the folder if it is a default mailbox folder such as:Mailbox – Caleb>_Inbox to be workedIt will not move to from the “Mailbox – Phoenix, CPC” inbox to the folder that is titled “_Inbox to be worked” within that mailboxI have been digging for weeks to get this done. ANY help would be extreemly welcome

    • http:// 6:21 pm on May 14, 2009 Permalink | Reply

      This is great, can you create a macro to move email to a folder when I close outlook?e.g. Move emails from helpdesk@me.com to a folder called !HelpDesk

    • http:// 12:57 am on August 27, 2009 Permalink | Reply

      If you want to move email to a nested folder, replace Set objFolder = objInbox.Folders(“_Reviewed”) with Set objFolder = objInbox.Folders.Item(“Level_1_Folder_Name”).Folders.Item(“Level_1_Folder_Name”).Folders.Item(“Level_1_Folder_Name”)

    • http:// 3:16 pm on September 17, 2009 Permalink | Reply

      how would you replace the below if you wanted to move the message into a Public Folder instead of a personal folder?Set objFolder = objNS.Folders.Item(“Personal Folders”).Folders.Item(“Archive”).Folders.Item(“2008″)

    • http:// 3:27 pm on September 17, 2009 Permalink | Reply

      Also curious, how would you move from one public folder to another public folder?Thanks guys!

    • http:// 8:23 pm on December 9, 2009 Permalink | Reply

      The macro works great but I have a problem. How do you move a Read and/or delivery receipt email. Those emails(reports)don’t move.

    • http:// 4:47 pm on February 2, 2010 Permalink | Reply

      Hii moved my mails to my desired folder but it also changes original date and time when i received the mail. how can i retain my original date and time of mail while moving all my mail to my other folder

      • Chewy Chong 10:35 pm on February 28, 2010 Permalink | Reply

        hey there! wow, i’m suprised people are still finding this post. i have been struggling with the huge piles of emails I get daily (hence my dab with coding) but recently found a free tool called “clearcontext”. it does all the email moving around that I need and maybe something you might find handy. give it a try and let me know what you think (no need to write any code).

        http://www.clearcontext.com

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel