Thursday, February 27, 2014

The best approach to schedule workflow in SharePoint

You can choose freeware HareP​oint Workflow ​Scheduler to do the job. It's a full-trusted solution and there is no source code. I didn't deploy it to any production environment, but it looks nice.

Or, if you are a developer, you may build a similar module like what I did 3 years ago. You have full control of all features, but, it's not something can be done in a couple of hours.

Recently I switched to PowerShell script and Windows Task Scheduler.

Use Windows Task Scheduler to run PowerShell script which triggers workflows is a simple solution with many extra benefit.

1. Don't need the help from developers, and there is no outage during deployment.

2. No extra license cost.

3. Easy to maintain, easy to extend.

4. Easy to schedule workflows remotely.

5. No outage during maintenance.

etc.

Any drawback? You need to understand PowerShell :-)

Below is the script I built to run workflows.  If you found any bug in it, please let me know.

Thanks for the post from Levente Rög, which saved me a lot of time.

---------------------------------

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction "SilentlyContinue"
cls

#rm function:/StartSiteWorkflow
function StartSiteWorkflow([string]$siteURL, [string]$siteWorkflow)
{
    Write-Host "StartSiteWorkflow start, ......" -ForegroundColor Green
    Write-Host "siteURL=$siteURL, siteWorkflow=$siteWorkflow" -ForegroundColor Green

    $site = Get-SPSite $siteURL
    $culture = [System.Globalization.CultureInfo]::InvariantCulture
    $wfAssociation = $site.RootWeb.WorkflowAssociations.GetAssociationByName($siteWorkflow, $culture)

    if ( $wfAssociation )
    {
        $assocData = $wfAssociation.AssociationData

        $wfRunOption = [Microsoft.SharePoint.Workflow.SPWorkflowRunOptions]::Synchronous
        $site.WorkflowManager.StartWorkflow($site, $wfAssociation, $assocData, $wfRunOption)
    }
    else
    {
        Write-Error "Workflow association '$siteWorkflow' not found on target web site '$siteURL'."
    }
}

function StartListWorkflows([string]$webURL, [string]$listName, [string]$listWorkflow)
{
    Write-Host "StartListWorkflows start, ......" -ForegroundColor Green
    Write-Host "webURL=$webURL, listName=$listName, listWorkflow=$listWorkflow" -ForegroundColor Green

    $web = Get-SPWeb -Identity $webURL
    $manager = $web.Site.WorkFlowManager

    $list = $web.Lists[$listName]
    if ($list -ne $null)
    {
        $culture = [System.Globalization.CultureInfo]::InvariantCulture
        $assoc = $list.WorkflowAssociations.GetAssociationByName($listWorkflow, $culture)
        if ($assoc -ne $null)
        {
            $data = $assoc.AssociationData

            $items = $list.Items
            $myArrayList = New-object System.Collections.Generic.List[int]
            Write-Host ""
            Write-Host "Collecting item id......"
            foreach($item in $items)
            {
                Write-Host -NoNewline ".";
                $myArrayList.add($item.ID)
            }  

            $arraycount = $myArrayList.Count;
            Write-Host ""
            Write-Host "Trigger all " $arraycount " workflows......"
            for ($i = 0; $i -lt $arraycount; $i++)
            {
                Write-Host -NoNewline "s";
                $itemCurrent = $list.GetItemById($myArrayList[$i])

                $itemCurrent["Action"] = "Update"    #may not need this step
                $itemCurrent.SystemUpdate()          #may not need this step

                $itemCurrent = $list.GetItemById($myArrayList[$i])
                $wfRunOption = [Microsoft.SharePoint.Workflow.SPWorkflowRunOptions]::Synchronous
                $wf = $manager.StartWorkFlow($itemCurrent,$assoc,$data,$wfRunOption)
                Write-Host -NoNewline "e";
            }
            Write-Host ""
            Write-Host ""
        }
        else
        {
            Write-Host "invalid workflow name." -ForegroundColor Red
        }
    }
    else
    {
        Write-Host "invalid list." -ForegroundColor Red
    }

    $manager.Dispose()
    $web.Dispose()
}

StartSiteWorkflow "http://SharePointServer/sites/site1" "Site Workflow Name"

StartListWorkflows "http://SharePointServer/sites/site1" "ListName" "List Workflow Name"

No comments:

Post a Comment