Thursday, June 7, 2012

Sharepoint 2010 Globally Reusable Workflows does not update WF instance in Subsite if re-published: PS Script save me

I defined a Globally Reusable WF for a custom Content Type in root site, with a custom form with InfoPath.
I defined a sub site with a list using the global WF template created for its Content Type.
Everything works without problems.

Now I need to change the WF (both in form and in the process).
BUT..
If I edit only the form with InfoPath and then I publish the form, I see correctly the new form in WF on subsites.
If I change the WF logic too (any actions) and publish WF (in root site), changes are not perceived by WF on subsites.
WF on subsite is updated only if, on subsite, I open WF to change (from browser) and save it.

I expect that you can update all WF in subsite using template in root site, without having to reopen and resave each WF in each subsite.
I don't understand if it's a bad configuration or a issue on Globally Reusable WF.

(I opened question in Technet Forum, here)

UPDATE: Sometimes, I update a WF (form and logic) and logic has been correctly published in all web site, but form does not show my modification...

So, unique solution I found for all my subsites is to delete workflow association and recreate it, for each site... But it's a long task, depend on how many subsites you have.

I write this powershell script to automate removing and adding operation.
This helps me, but cannot solve problems..
If you don't have access to Server to run PS Scripts, you cannot use this way...


[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
$urlRoot = "http://[SERVER]"
#array of workflow name to update
$wfNames = "Workflow Name 1"," Workflow Name 2", "Workflow Name 3"

$site = Get-SPSite $urlRoot

foreach($web in $site.AllWebs){

 $url = $web.Url

 #exept for root site (if needed)
 if($url -ne $urlRoot){

   foreach($wfName in $wfNames){

     "Adding workflow $wfName to $url"

     $list=$web.Lists["LISTNAME"]
     $taskList=$web.Lists["WF TASK LIST NAME"]
     $historyList=$web.Lists["WF HISTORY LIST NAME"]
     $ct=$list.ContentTypes["CONTENT TYPE"]

     "Search workflow $wfName"
     foreach($wf in $ct.WorkflowAssociations)
     {
       if($wf.Name -eq $wfName)
       {
         "Remove workflow $wfName"
         $ct.WorkflowAssociations.Remove($wf)
         break;
       }
     }

     "Now add workflow $wfName"

     $culture=New-Object System.Globalization.CultureInfo("en-US")
     $wfTemplate=$web.WorkflowTemplates.GetTemplateByName($wfName,$culture)

     "Get wf template"
     $associationWF=[Microsoft.SharePoint.Workflow.SPWorkflowAssociation]::CreateListContentTypeAssociation($wfTemplate, $wfName,$taskList,$historyList)

    "Add Workflow $wfName"
     $ct.WorkflowAssociations.Add($associationWF)
     $ct.UpdateWorkflowAssociationsOnChildren($true,$true,$true,$false)
  }
 }
 $web.Dispose()
}