Carbon Based Lifeforms–Music to code by

Every once and a while you come across a band that seems to just click with you. It was about this time last year when I discovered Carbon Based Lifeforms (CBL), and I have been completely hooked on them ever since.  In fact, I like a lot of the stuff from the groups signed with Ultimae, but it’s CBL I sink most of my money into.  It’s been a long time that just about every single release of a given group has moved me the way CBL has.  For me, they are just frakin’ awesome.

 

 

It was a post Martin Lindhe (a.k.a. Bassic) had posted on his Facebook wall that turned me onto CBL.  It went something to the effect of “Can’t seem to get Interloper by CBL out of constant rotation lately”, or something like that.  So I went and checked out Interloper and I was hooked.  I immediately turned back around and swooped up World of Sleepers and Hydroponic Garden.  And I’m dying to get my hands on Twentythree.

I can honestly say, that at some point during each day when I’m coding, I shuffle up my collection of CBL to code by.

If you are into Ambient Music, I highly recommend you check them out.

I certainly like all their tracks, but probably my favorites are listed below if you want a direct sampling of their music:

I hope you enjoy!

– Keith

Celebrating the Ultimate Answer to Life, The Universe and Everything.

Most people have New Years Resolutions, but not really me. 

Instead, each year on this day, is when I take a moment and plan my goals for the next year ahead of me.

This particular year, I get to celebrate the Ultimate Answer to Life, The Universe and Everything.

Every year (primarily on this day) but also on Christmas, I hop into my car; take a long drive; pass through the neighborhood I grew up in; and listen to one of the most inspirational (in my opinion of course) music releases in my collection.   When I’m finished with that one, I immediately plug in the second most inspirational one (And always end with this very special track).

It’s something I’ve done now for nearly 30 years.

So I got up early this morning, to try to get most of my work for the day done.  Clearing my “todo” list so that I can head out with a clear mind; to drive; to meditate; to reflect; to look at where I’ve been; and to look forward to what the future has in store for me.

Generally during my ritual drive, I think of many of the bad things that have happened, and the many mistakes I’ve made throughout life.  Those bring me down a bit.  But I put a concentrated effort to focus on ALL of the MANY positive things that have occurred.

As I sit here writing this, I’m waiting on my youngest child to get dressed to take her off to daycare for the day, and then head out for my “trip” down memory lane.  And I’m reminded by the ultimate positive thing in my life.  The fact that I have two very wonderful daughters in my life.  And many, many more.

Do YOU have a ritual you perform every year? I’m curious to know.

– Keith

Categories Uncategorized

Programmatically reading SharePoint Designer Workflow XOML files at run time.

I’m working on a project where I need to read the actual XOML file for a SharePoint Designer workflow at runtime during a few of my custom activities I’m developing.  The reason, is that I have to enumerate and inspect all the workflow variables the end user has defined.  The only way to do this, is to actually peek back into the XOML file for the workflow.

After poking around and searching for a few days without any luck, I ran across this posting from Joe Zamora: “Query/enumerate all declarative workflow templates in an SPWeb and programmatically read the XOML files

Perfect! I thought.  This was exactly what I was looking for. I took his sample, cleaned it up a bit, and wrote a method to get to the XOML file. 

 

public static string 
  GetXOMLFromWorkflowInstance(SPListItem item, Guid wfInstanceId)
  {
    SPWorkflow wf = new SPWorkflow(item, wfInstanceId);
    SPWorkflowAssociation assoc = 
      item.ParentList.WorkflowAssociations[wf.AssociationId];

    XmlDocument doc = new XmlDocument();
    doc.Load(new StringReader(assoc.SoapXml));

    XmlNode node = doc.SelectSingleNode("/WorkflowTemplate");
    XmlAttribute attribute = node.Attributes["Name"];
    string wfName = attribute.Value.Replace(" ", "%20");            
    string webRelativeFolder = "Workflows/" + wfName;            
    string xomlFileName = wfName + ".xoml";

    SPFolder wfFolder = assoc.ParentWeb.GetFolder(webRelativeFolder);
    SPFile xomlFile = wfFolder.Files[xomlFileName];

    doc = new XmlDocument();
    using (Stream xomlStream = xomlFile.OpenBinaryStream())
    {
      doc.Load(xomlStream);
    }
    return doc.OuterXml;
  }

 

As you can see the workflow’s folder and file names, when initially saved, utilize the name you defined in SharePoint Designer. So, if I create a workflow and call it “My Cool Workflow”, then a folder get’s created in the Workflows folder of the site with the name “My Cool Workflow”, and it’s resulting .xoml file is stored within that folder with the name.  So it’s pretty easy to construct the path to the xoml file from that.

All was grand for about 1 hour.

And then….

While demonstrating the latest build to a customer, we renamed the workflow between a test, and everything broke.  After a bit of debugging, I figured out what the problem was.

The method above depends on the “Name” attribute within the WorkflowTemplate element to derive it’s path to the underlying XOML file in the site.  The problem, as I mentioned above, revealed itself when we renamed the workflow.  The name attribute could no longer be relied on as it possibly will NOT match the underlying workflow folder container, etc.  The workflow folder/.xoml etc will always keep the original name.  So, taking the example of the workflow originally being named “My Cool Workflow” and changing it to anything else doesn’t change the fact that the workflow will forever be stored in a folder called “My Cool Workflow”.

So, back to the drawing board for a few days trying once again to figure out HOW to get back to the XOML file itself.  As Joe found, the Object Model just doesn’t do a very good job of actually letting you determine that (that I know of), but then I noticed something in the SoapXml of the workflow association.  Aha!   It contains an Instantiation_FormURI element that has the path to the xsn of the instantiation form.  Well hey!  We can just use that, replace .xsn with .xoml and we’re back in the game.

 

public static string 
  GetXOMLFromWorkflowInstance(SPListItem item, Guid wfInstanceId)
  {
    SPWorkflow wf = new SPWorkflow(item, wfInstanceId);
    SPWorkflowAssociation assoc = 
      item.ParentList.WorkflowAssociations[wf.AssociationId];

    XmlDocument doc = new XmlDocument();
    doc.Load(new StringReader(assoc.SoapXml));

    XmlNode node = 
     doc.SelectSingleNode("/WorkflowTemplate/Metadata/Instantiation_FormURI/string");

    string xsnPath = node.InnerText;
    xsnPath = xsnPath.Replace(" ", "%20");

    string webRelativeFolder = 
      xsnPath.Substring(0, xsnPath.LastIndexOf('/'));
    string xomlFileName = 
      xsnPath.Substring(xsnPath.LastIndexOf('/') + 1);
    xomlFileName = 
      xomlFileName.Replace(".xsn", ".xoml");

    SPFolder wfFolder = assoc.ParentWeb.GetFolder(webRelativeFolder);
    SPFile xomlFile = wfFolder.Files[xomlFileName];

    doc = new XmlDocument();
    using (Stream xomlStream = xomlFile.OpenBinaryStream())
    {
      doc.Load(xomlStream);
    }
    return doc.OuterXml;
  }

The only concern I had with this approach, is what if there wasn’t an instantiation form?  Well, it turns out that SharePoint Designer won’t ALLOW you to not have one, even if it doesn’t contain anything.  If you delete the instantiation form, then save the workflow again, it will just generating it one more time.  So we’re guaranteed to have an Instantiation_FormURI element within SPWorkflowAssociation.SoapXml.

Hope this helps someone else!

[Update: 07/08/2011]

Well apparently the mandatory instantiation form does NOT exist by default in SharePoint Designer 2007 workflows, so it currently is NOT a reliable way for it.

[Update: 07/20/2011]

For SharePoint Designer 2007 workflows, it looks like you can depend on the “InitiationUrl” attribute.

The updated method I wrote for 2007 looks similar to this:

 

public static string 
  GetXOMLFromWorkflowInstance(SPListItem item, Guid wfInstanceId)
  {
    SPWorkflow wf = new SPWorkflow(item, wfInstanceId);
    SPWorkflowAssociation assoc = 
      item.ParentList.WorkflowAssociations[wf.AssociationId];

    XmlDocument doc = new XmlDocument();
    doc.Load(new StringReader(assoc.SoapXml));

    XmlNode node = doc.SelectSingleNode("/WorkflowTemplate");

    string xsnPath = node.Attributes["InstantiationUrl"].Value;
    xsnPath = xsnPath.Replace(" ", "%20");

    string webRelativeFolder = 
      xsnPath.Substring(0, xsnPath.LastIndexOf('/'));
    string xomlFileName = 
      xsnPath.Substring(xsnPath.LastIndexOf('/') + 1);
    xomlFileName = xomlFileName.Replace(".aspx", ".xoml");

    SPFolder wfFolder = assoc.ParentWeb.GetFolder(webRelativeFolder);
    SPFile xomlFile = wfFolder.Files[xomlFileName];

    doc = new XmlDocument();
    using (Stream xomlStream = xomlFile.OpenBinaryStream())
    {
      doc.Load(xomlStream);
    }
    return doc.OuterXml;
  }

– Keith