Why VSTO 3.0, Visual Studio 2008, SharePoint+Windows Workflow And InfoPath Might Give You A Hernia

This is just a post containing all the issues I’ve run into over the last six months while working with MOSS Workflows, InfoPath and Visual Studio 2008/VSTO 3.0. I’ve been using these tools in this combination for a while now, but it’s only the last six months where I decided to take a note every time I ran into something. Don’t get me wrong though. This is more of a post aimed at helping others in their quest for abdominal hull-integrity while working with these tools, not attacking the toolset. Ultimately, the Office Suite and the corresponding tools are working together better than ever before, but unfortunately with large teams working relatively independently you’re just going to get these kind of problems. To be brutally honest, I think VSTO 3.0 is a saddle-sore on the otherwise supple and leathery hide of Visual Studio 2008 and the disparity in their respective product quality is way too pronounced to be ignored.

Anyway, I’m not going to make much attempt to explain each case for non-SharePoint people, but if you’re involved in this area, you’ll know where I’m coming from. The following list contains Glitches and Gotchas.

Glitches

First though, the Glitches, in no particular order. These are the lovingly hand-crafted defects and “product quality issues” that will first cause your stomach muscles to contract somewhat, then violently spasm so hard that that first loop of intestine will pop out to nestle amongst the fat cells and veins in the fleshy meadow of your lower-epidermis. Don’t say I didn’t warn you.

Publish an Installable Form Template (requires Visual Studio)

vs2008-vs-not-installed-properly

If you try to publish a form as "an installable template (requires visual studio)" from within Visual Studio 2008 (even with sp1), VSTO, in its infinite wisdom tries to use visual studio 2005 devenv.exe executable to do it! And it fails spectacularly 'cos it's not installed, or if it is installed it's part of some vs-shell install for some other office app like office macros IDE, or Internet Explorer’s “script debugger” shell for example.

vs2008-infopath-vs2005

Publishing a Form to an explicitly-included Managed Path

Trying to publish a form to a SiteCollection sitting on an explicitly-included managed path fails with "getting the site content type columns failed." Workaround? Don’t publish forms to Managed Paths. It’s b0rked.

“An exception occurred during loading of business logic” - Publishing XSNs with CodeBehind to SharePoint

If you perform a cursory search for the title, you’ll find lots of herniated VSTO users having issues with this. InfoPath Forms Services on MOSS Enterprise is a fickle beast; a beast that will have you tucking those intestinal loops back into your torso with a pencil before you can say “FileNotFoundException, whuh?”

XSN files are actually CAB files. When Forms Services loads them up to be rendered into Browser Forms, it has to load the embedded DLL into memory. It has an extremely hard time doing this sometimes. Particularly when you store your XSN files in a subdirectory under your workflow feature, say like one called Forms. It appears that the form loads ok, but Forms Services is looking for the DLL in the root of your feature. Even sometimes if you have the XSN in the root of your feature, it still won’t find and extract/load the embedded DLL. The only way to avoid this it appears is to manually extract the DLL and place it in the root of the feature yourself after you have deployed the workflow solution.

Some strange things I’ve observed about Forms Services on MOSS Enterprise:

  • Uploading a codebehind-XSN  file via central admin automatically extracts dll/pdb into feature directory but...
  • Deploying a codebehind-XSN with  workflow feature does not extract dll/pdb.
  • Upgrading a codebehind-XSN with central admin creates new subdir in feature folder, modifies feature.xml to point to it but does not extract the form's codebehind dll/pdb into new subdir either.

These seem to be some rather serious looking issues to me.

VSTO Designer ToolPane Content Shrinks

Occasionally the Design ToolPane in VS2008/VSTO inexplicably changes size, with the contents of it being set at about 1cm wide.b0rked-vsto-toolpane

A restart of Visual Studio or close/reopen of the project usually fixes this.
Workflow Designer Screws Up Layout of Nested States

The workflow designer in VS 2008 (even sp1) will screw up the formatting of nested states in a state machine workflow - they get randomly offset to the left or right so they are half occluded by the containing state. Yay.

Views ToolPane Is Blank For a Form that has Views

Views created in infopath sometimes do not appear in vs2008 project built around that imported XSN. Weirdly, the toolpane is completely white/blank. A restart of Visual Studio or close/reopen of the project usually fixes this.

Manipulating Files In “InfoPath Form Template” Project Folder Is a Bad Idea

Deleting/modifying/renaming a file in the "infopath form template" meta-folder in Visual Studio 2008 does not fix the reference in the manifest.xsf file. The form is then impossible to open until you fix the references within the manifest by closing the form designer and opening the XSF with the XML handler through a right-click. Why does VSTO even let you modify embedded resources if it won’t update the manifest for you?

The magical secondary DataSource ItemMetadata.xml

The secondary DataSource (for receive data) ItemMetadata.xml has _two_ ways of being added as a resource - the second way (prompted at end of import). You can either add it as a resource when you initially point VSTO/InfoPath at it, or if you don’t do it then you get a second chance at the end of import to add it as a resource. This is confusing.

Converting an embedded DataSource to site-relative format and placing into a  Data Connection Library can leave the required field "Title" empty

This enforces the UDCX files to be permanently checked out - trying to update the title field by hand does not work - it remains blank at every attempt to change it when done directly or via bulk edit DataGrid view. It sometimes exclaims that the files are checked out to another user even though they are plainly checked out to me. Worst of all, only *I* can use the InfoPath form that uses this DataSource so it’s starts out a looking like “it works for me” issue.  Anyone else cannot use the form - DataSource loading fails - ULS log says "root element is missing" - after much debugging, it appears that anyone (apart from me the author) attempting to download the UDCX file gets a 0 length file - you can test this by getting the poor user to try to download the UDCX from the connection library. This is because only an author of a checked-out file can read it. 

Hacky Fix: Remove ReadOnly attribute from the list-level UDCX content type and mark the Title column as optional, then check-in the connections. Title be damned!

This all started when I enabled Versioning for the connection library before converting my data sources. Not sure if that’s relevant.

BDC randomly losing ServerContext while inside Event Receiver triggered from Workflow context

The TLS slot for the resource provider SqlSessionProvider sometimes ends up being null on the Event Receiver's thread. If you’re not following me, you probably don’t need to understand this any further.

Gotchas

These are not so much glitches are they are things that can trip you up and/or be considered “non-obvious” behavioural quirks. While they may give you an upset tummy, you are not going to be trussed up in a Spigelian torso-bangle any time soon.

A Workflow Continually Spawns New Instances of Itself

When you have a workflow added to a document library and the workflow updates the list item when it is running, a new workflow will spawn once the .Update() method is executed on the list item. To update the item without having a new worklfow started, use .SystemUpdate(). Duh.

"The database returns an error. Failed to enable constraints." When InfoPath DataBinds

Changing the query directly in a UDCX file inside a data connection library may cause "The database returns an error. Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints" errors from live InfoPath forms because the data source schema in InfoPath no longer matches (especially if you increase the length of a returned field) - after you change the UDCX, you must go through the "manage data connections" and choose "modify" for that connection and go through the wizard without changing anything. This will cause InfoPath to re-sync the schema.

How The Hell Can I Render The Form Version On The Form Itself?

Tip: insert form version with the expression: substring-before( substring-after( /processing-instruction()[local-name(.) = "mso-infoPathSolution"], 'solutionVersion="'), '"')

I can’t remember where I got this, I didn’t write it myself. Thanks to the original author.

Why Can’t SharePoint Find My Forms for my Workflow?

The Form URN will change if you don't name your form exactly as you did (e.g. accept the default) in "file > form properties" when publishing it with the publishing wizard.

Why Can’t My Workflow Forms Find My Data Connections?

Site relative data connections stored in a data connection library work fine for InfoPath published forms bound to a content type in a site; also form security will stay at domain. But they can’t be found if these same forms are used in a workflow. Use “centrally managed” data connections instead.

Why Does Visual Studio Put Referenced DLLs Bound For the GAC Into My InfoPath XSN?

If you reference other feature projects in the same solution that deploy into GAC, be sure that they exist in the GAC before building the InfoPath project's XSN - if they are not in the GAC, they will be copied into the XSN by default. Duh.

How Do I Uninstall My Workflow I was Debugging In Visual Studio?

Workflow features deployed via vs2008 F5/start debugging have no obvious means of being "undeployed." you must use VSTO 1.0 PowerTools "Feature Sweeper" to remove it; this is a dependency for workflow forms registered in central admin.

Why Are The TaskProperties Hashtables So Weird?

ExtendedProperties Hashtables leaves root XML fields as keys, and nested xml as my:schema formatted XML for Hashtable values. Strangely, the Workflow API has a public XmlToHashtable method on a utility class, but not the inverse to pull it back out of ExtendedProperties. Duh.

Where The Hell Did The Form Publish Menu Disappear to?

You cannot publish the InfoPath form unless you have the designer open, even though you can only have one form per project and you might just have a single project in the solution. This is annoying when your forms are large and sluggish to open.

Why do some VS SharePoint Activities have a User (string) property and others a UserID (int) property?

I wish I knew. This is just another silly design (in)decision. All SPUsers in SharePoint have both a Login (string) and a PrincipalID (int). If you want to set the Logging Activity’s UserId (int) to the id of a person who performed a Workflow Modification User (string), you have to convert, persist and expose these properties yourselves before you can bind to an activity using the designer. Duh.

I use a method like this:

id = Contact.FromName(executor, this.workflowProperties.Web).PrincipalID;
Why is Visual Studio 2008  SP1’s Workflow Designer Host still such a dog?

You and thousands of other people would love to know the answer. IMHO, it’s too complex to have been written in Managed Code (e.g. C#). It should have been native C++ from day one. All that synchronizing intellisense, XOML and the visual designer is just too much for it. God help you if you throw in any real-time refactoring tools on top of that.

Summary

Despite all this moaning, SharePoint in conjunction with Visual Studio 2008 is a powerful combination. Nothing to be sniffed at all; I actually love it (most of the time.)

Have fun.

What’s the difference between Set-Content and Out-File ?

Specifically, get/set-content works with providers that facilitate content reading and writing. Out-File works only with the FileSystem provider and is for all intents and purposes an alias to the > redirection operator.

An interesting thing to note about get-content and set-content is that you use them indirectly every day. Both the variable and function providers support get- and set-content, and when you use the dollar ($) syntax to read or write to a variable, you are implictly calling get-content and set-content against a path in the variable provider. E.g.

ps> $foo = 5

...is the same as:

ps> ${variable:foo} = 5

e.g. set the content of item foo in the psdrive called "Variable" to 5. This is why you can also write to a file like:

ps> ${c:\temp\foo.txt} = "some content"

...and read it back with:

ps> ${c:\temp\foo.txt}
some content

Ultimately, when using the $ syntax, the "variable" drive is the default drive to read and write content from. Elegant, eh?

Resharper 4.1 is released

Resharper (or R#) is an absolute gem of a tool. After using it for a year, I really don’t know how I got along without before. If you write code in .NET (C# or VB.NET), you owe it to yourself to try it out. Version 4.0 was the first to support C# 3.0:

ReSharper 4 Full Edition and C# Edition extend language support to C# 3.0, including LINQ, implicitly typed locals and arrays, extension methods, automatic properties, lambda expressions, object & collection initializers, anonymous types, expression trees, and partial methods. ReSharper not only analyzes the new constructs, but provides C# 3.0-related enhancements in a number of areas — specifically, warnings, suggestions, code completion options, refactorings, and templates.

The guys at Jetbrains just released versus 4.1. They offer a free thirty-day trial over at http://www.jetbrains.com/resharper/ – do it!

VMWare VMNET Adapters Triggering Public Profile for Windows Firewall

Are you sick and tired of switching the VMWare virtual network adapters from the “public” network profile to a “private” network profile each time you reboot or do something else that causes Vista/Win2008 to forget what you told it to do ten minutes ago? This is probably a familiar sigh (I’m using Workstation):

vmware-unidentified-network

As you can see, the lower two connections are seen to be in a “Public network.” This has the net effect of making Windows believe the whole machine is exposed to a public network, and it will trigger the public profile for Windows Firewall. This is normally a good thing, but in this case it’s just an annoyance. These two network connections are not actually external gateways that can let in the bad guys. They are just dummy adapters for VMWare’s host bridging which allow the virtual machine to access the host machine’s network. Because they don’t identify themselves properly, they are flagged as an “unidentified network,” and your changes are never persisted.

So what do you do? The magic information is buried in MSDN:

Vista automatically identifies and monitors the networks to which a computer connects. If the NDIS_DEVICE_TYPE_ENDPOINT flag is set, the device is an endpoint device and is not a connection to a true external network. Consequently, Windows ignores the endpoint device when Windows identifies networks. The Network Awareness APIs indicate that the device does not connect the computer to a network. For end users in this situation, the Network and Sharing Center and the network icon in the notification area do not show the NDIS endpoint device as connected. However, the connection is shown in the Network Connections Folder. Also, if NDIS_DEVICE_TYPE_ENDPOINT is set, the Windows Firewall ignores the connection when Windows Firewall enforces public, private, or domain policies.

So I hacked together a PowerShell script that will scan your adapters for VMWare’s virtual NICs and make the necessary registry changes. It will also disable/enable cycle the adapters so that the changes take effect. After this is done, you will see them in your Network Connections page – albeit lacking a network category -- and the connections will no longer appear in the Network and Sharing Center nor will they affect your Windows Firewall policy no matter how many times you reboot!

vmware-unidentified-network-1

Here’s the script source below. It requires that you run it in an elevated shell in order to write the registry changes and cycle the adapters’ enabled state.

  1. # see http://msdn2.microsoft.com/en-us/library/bb201634.aspx  
  2. #  
  3. # *NdisDeviceType   
  4. #  
  5. # The type of the device. The default value is zero, which indicates a standard  
  6. # networking device that connects to a network.  
  7. #  
  8. # Set *NdisDeviceType to NDIS_DEVICE_TYPE_ENDPOINT (1) if this device is an  
  9. # endpoint device and is not a true network interface that connects to a network.  
  10. # For example, you must specify NDIS_DEVICE_TYPE_ENDPOINT for devices such as  
  11. # smart phones that use a networking infrastructure to communicate to the local  
  12. # computer system but do not provide connectivity to an external network.   
  13. #  
  14. # Usage: run in an elevated shell (vista/longhorn) or as adminstrator (xp/2003).  
  15. #  
  16. # PS> .\fix-vmnet-adapters.ps1  
  17.  
  18. # boilerplate elevation check  
  19.  
  20. $identity = [Security.Principal.WindowsIdentity]::GetCurrent()  
  21. $principal = new-object Security.Principal.WindowsPrincipal $identity 
  22. $elevated = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)  
  23.  
  24. if (-not $elevated) {  
  25.     $error = "Sorry, you need to run this script" 
  26.     if ([System.Environment]::OSVersion.Version.Major -gt 5) {  
  27.         $error += " in an elevated shell." 
  28.     } else {  
  29.         $error += " as Administrator." 
  30.     }  
  31.     throw $error 
  32. }  
  33.  
  34. function confirm {  
  35.     $host.ui.PromptForChoice("Continue", "Process adapter?",  
  36.         [Management.Automation.Host.ChoiceDescription[]]@("&No", "&Yes"), 0) -eq $true 
  37. }  
  38.  
  39. # adapters key  
  40. pushd 'hklm:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}' 
  41.  
  42. # ignore and continue on error  
  43. dir -ea 0  | % {  
  44.     $node = $_.pspath  
  45.     $desc = gp $node -name driverdesc  
  46.     if ($desc -like "*vmware*") {  
  47.         write-host ("Found adapter: {0} " -f $desc.driverdesc)  
  48.         if (confirm) {  
  49.             new-itemproperty $node -name '*NdisDeviceType' -propertytype dword -value 1  
  50.         }  
  51.     }  
  52. }  
  53. popd  
  54.  
  55. # disable/enable network adapters  
  56. gwmi win32_networkadapter | ? {$_.name -like "*vmware*" } | % {  
  57.       
  58.     # disable  
  59.     write-host -nonew "Disabling $($_.name) ... " 
  60.     $result = $_.Disable()  
  61.     if ($result.ReturnValue -eq -0) { write-host " success." } else { write-host " failed." }  
  62.       
  63.     # enable  
  64.     write-host -nonew "Enabling $($_.name) ... " 
  65.     $result = $_.Enable()  
  66.     if ($result.ReturnValue -eq -0) { write-host " success." } else { write-host " failed." }  
  67. }  

Have fun.

About the author

Irish, PowerShell MVP, .NET/ASP.NET/SharePoint Developer, Budding Architect. Developer. Montrealer. Opinionated. Montreal, Quebec.

Month List

Page List