January 2009 - Posts

The other day, I posted about how to write a simple workflow to copy files to the records center whenever they were created or modified.  Well the workflow I provided worked in all of the following cases.

  • Add new item
  • Upload Item
  • Upload new version to existing item
  • manual check out then check back in (with no changes to the doc.)
  • Edit document properties (When checkout required is set on the library)

Of course there was one place that I found that it doesn't work.  It is when you use the New Document button or edit an existing document directly with Office 2007.  The reason for this is that when you have a document open with Office, it creates a Short Term Check Out for the period of an hour.  It also continues to reestablish the lock until you close the Office application (i.e.: Microsoft Word).  Records Center will not accept any document that is currently checked out.  This presented an interesting challenge on how to deal with this.  The first thing I tried was adding code to check in the file (i.e.: SPFile.CheckIn).  This method does not work when the CheckOutType is ShortTerm.

I tried an ItemEventReceiver to see if closing Office would trigger the ItemCheckedIn event, but it in fact does not.  This means I can't handle this scenario that way either.  So what I came up with was a hack, but it does in fact get the job done (provided the user eventually closes the Office application).  Here is what it looks like.


I did say hack, didn't I?  That's exactly what it is.  The While activity contains the following code condition.  All it does it execute the contents of the while activity as long as the CheckOutStatus is set to ShortTerm (meaning the user still has Microsoft Word open).

private void IsShortTermCheckedOut(object sender, ConditionalEventArgs e)


    e.Result = (workflowProperties.Item.File.CheckOutStatus == SPFile.SPCheckOutStatus.ShortTerm);


As you can see there is a Delay activity in there.  These actually seem to work now, but you do need to be sure that you have the latest version of the .NET Framework installed as well as all updates applied to SharePoint.  Otherwise there is a good chance that your workflow will never wake back up.  I have the delay set to 15 minutes.  This is because the workflow timer job runs every 15 minutes (by default).

Other than that the code is all the same from the previous post.  I've ran it through several tests and it seems to work for me.  I'd like to think there is a better way to handle this, but I can't think of anything right now.  You might consider adding code to the while activity so that it eventually terminates if the user never closes Office, but that is up to you.

Now, I have always known there are some oddities when accessing a SharePoint server by IP and as a practice I tend to avoid it.  I am sure the issue I am about to describe relates to alternate access paths in some way, but I thought I would tell people about it in case someone else runs into it.  The scenario I have is quite simple.  I have a custom workflow attached to a document library that executes whenever a file is created or modified.  What I discovered was that when I was accessing the site on my virtual machine by name, the workflow was executing.  When I tried to reach it from the host machine by IP address, it did not execute.  It didn't give an error or anything.  It simply did not start.  The reason I was accessing by IP to begin with is because the server name wasn't resolving on my host machine and I was being too lazy to fix it.  Next time, I won't make this mistake.  Workflows will not automatically start when you specify the server by IP address in your browser.

with 4 comment(s)
Filed under: ,

Today's topic is certainly one of those features that seems like it should be included out of the box.  Luckily, it is pretty simple to implement.  My required was that I needed a file send to the records center whenever it is created, modified, or checked in.  I considered using an ItemEventReceiver, but decided creating a simple workflow would be easier to attach to multiple document libraries.  You could use the same code in an event receiver though.


My workflow is simple.  It contains an OnWorkflowActivated and a Code activity.  The OnWorkflowActivated activity is only used to set the workflowProperties object.

private void SendOfficialFile(object sender, EventArgs e)


    SPFile documentFile = workflowProperties.Item.File;


    string recordSeries = documentFile.Item.ContentType.Name;

    string additionalInformation;

    OfficialFileResult fileResult = documentFile.SendToOfficialFile(recordSeries, out additionalInformation);


As you can see there really isn't a lot of code required to make this happen.  I simply get the SPFile object from the SPWorkflowProperties object and call its SendToOfficialFile method.  This method takes two parameters, recordSeries and additionalInformation (an out parameter).  It took me a while to find some documentation on what to put in these.  The first example, I saw just left the recordSeries parameter blank.  This will work, but it will also cause all of your files to go to the Unclassified Records routing rule.  After some digging, I discovered you are supposed to set it to the name of the item's content type (which would have a routing rule matching its name).  The OfficialFileResult enum will give you a value of Success if the file was submitted alright, otherwise it will give you a value or MoreInformation which means you can examine the value of the additionalInformation parameter to find out what went wrong.

Once you have your code activity completed, you are ready to compile and deploy the workflow.  Deploy the workflow and attach it to your document library.  Choose wether you want it to execute on new items or modified items.  Once you have done that, you are ready to test it out.  Upload a file or modify an existing one and check your records center to see if the file is there.  Before you start this process, be sure and verify that your records center is functioning to begin with by manually sending a file to the records center with the send to menu option.

At a minimum, this is all that is really required to get a file into the records center.  As usual, I left out exception handling code to keep the post short.  One thing to note, Records Center requires the file to be checked in.  You can choose to handle this.  Some people may not want the file to be sent in the records center, others might want it to just be checked in.  You can determine if the file is checked in by looking at the Level property on the SPFile object.

For more information on handling ShortTerm CheckOut locks, see this post.

A while back, I posted about how to Remote Debug a task form for a workflow.  The post I made didn't clearly specify I was talking about a task form so I went back and updated it.  This made me thing that I haven't covered how to debug a Full Trust form outside of a workflow.  Although the process is similar, I thought I would take the time today to discuss how it is works.

As you probably know, full trust forms that you deploy for use in form libraries must be uploaded via the Manage Form Templates page in Central Administration.  With a workflow, you would copy your DLL and PDB file for the form into the feature folder of the workflow.  Since a workflow is not involved in this case, the form obvious goes somewhere else.  If you examine your FEATURES folder in the 12 hive you will notice that you may have some folders starting with FT-01 followed by a guid (for example FT-01-3b866d3d-cc74-ec32-8fc2-e52f0839dd4f).  These are folders created when you upload a form template.

When you open the folder, you will see that it will contain multiple subfolders starting with solution.xsn followed by a version number.  It creates a new folder for every version of the form you upload.  Find the latest version number and open that folder.  In each folder you will see an XSN, DLL, and PDB file.  The template manager is nice enough to copy the PDB file for you (assuming you compiled it in debug mode).  Now you need to make sure that the DLL versions are the same between your compiled bin folder on your local machine and this folder.  More than likely they have different version, so you need to copy files from one folder to another (shouldn't matter which direction).  It seems like the versions should be the same but they never are.

At this point you can remote debug as usual.  Open up the Visual Studio Remote Debugging Monitor on the remote machine, determine the correct w3wp process, and set a breakpoint.  If you need more details see my other post on remote debugging InfoPath.

I have been building a large number of InfoPath Form Templates in Visual Studio 2008 lately and I have discovered it is can be quite the exercise in frustration when you want to put your files in TFS (or any source control for that matter).  There are a number of reasons for this, but it all starts with the fact that the form template designer does not like it when files are read only.  Unlike other project types that will automatically check out files that are needed, the InfoPath form template project will not do this.

Before, you begin working with an InfoPath template file in source control, be sure that you checkout (at a minimum) manifest.xsf.  For some reason any time you compile, this file must be checked out.  On top of that, if you want to publish your form, it seems to require that this file is checked out in all other form projects in your solution.  It looks like it does a build solution prior to launch the publish form template dialog.   As you are editing your form, other files in the project will more than likely need to be modified, so my recommendation is that you check the entire project.

As you are working, you might come to a point where you receive an error like the following when trying to save your file.

InfoPath cannot save the following form: InfoPath Form Template.  The form is read-only.

When this occurs, it really is a bad time because every time I have received it, the form was already checked out and not marked read only.  The only solution I have found for this is to close Visual Studio and restart it.  This can be particularly frustrating when you have made a bunch of changes to the form template as you will end up losing them.  For this reason, I have made a practice of attempting to save the form, before I start making any changes to it.

Another error that you may often run into is the following.

The operation cannot be completed.

This can occur when trying to publish or when trying to open the manifest.xsf file.  When this occurs, your best bet is to make sure all files in the project are checked out and restart Visual Studio.  If you are lucky, you will be able to open the form or publish it again.  If not, my recommendation is to go back to a previous version and hope for the best.

Another issue you might run into occurs when checking in.  If you try to check your files in while you still have manifest.xsf open in the form designer, you will get the following error.

The process cannot access the file 'MyTemplate.xsf' because it is being used by another process.

The designer seems to create a lock file so no external process can even read it.  Just make sure you close the file first before you try to checkin and you will be good.

I am excited to announce that I am speaking at SharePoint Saturday in Kansas City on February 7th.  This looks to be a great event with lots of SharePoint content.  I've never even been to Kansas City before believe it or not.  I'm looking forward to seeing everyone and meeting the other speakers.  I'll be presenting on Deploying Content with SharePoint.  There are lots of ways to automate this process, but every SharePoint developer needs to know how to do it manually so they can fix it when something goes wrong.  This is an intro level course built to get new SharePoint developers over the hump of code deployment.  Many thanks to the MOSS Lover for organizing this event.

with no comments