Start/Start workflow for list item of large list is one of tasks that I have been worked on and it was so excited. This article is just sharing the script code with a little explanation to avoid the error while it's executing.
Common Script
$username = "YOUR_TENANTACC" 
$password = "YOUR_PASS" 
$url = "YOUR_SITE_URL"
$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force 
# the path here may need to change if you used e.g. C:\Lib.. 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.WorkflowServices.dll" 
# connect/authenticate to SharePoint Online and get ClientContext object.. 
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) 
$clientContext.Credentials = $credentials 
$web = $clientContext.Web
$clientContext.Load($web)
$clientContext.ExecuteQuery()
$lists = $web.Lists
$clientContext.Load($lists)
$clientContext.ExecuteQuery()
$lst = $lists.GetByTitle("YOUR_LIST")
$clientContext.Load($lst)
$clientContext.ExecuteQuery()
#get all workflow subscription in your web/sub-site
$wfServicesManager = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager($clientContext, $web)
$wfSubscriptionService = $wfServicesManager.GetWorkflowSubscriptionService()
$wfSubscriptions = $wfSubscriptionService.EnumerateSubscriptions()
$wfInstanceSevice = $wfServicesManager.GetWorkflowInstanceService()
$clientContext.Load($wfSubscriptions)
$clientContext.Load($wfInstanceSevice)
$clientContext.ExecuteQuery()
#initalize the parameters for workflow
$dictionary = New-Object 'system.collections.generic.dictionary[string,object]'
$dictionary.Add("YOUR_VARIABLE", "YOUR_VALUE")
#in case, if you need to start workflow on some items, you could execute the query and start on those items    
$qry = New-Object Microsoft.SharePoint.Client.CamlQuery
$qry.ViewXML = "<View><Query><Where>YOUR_QUERY</Where></Query></View>"
$items = $lst.GetItems($qry)
$clientContext.Load($items)
$clientContext.ExecuteQuery()
$srb = $wfSubscriptions | Where-Object { $_.Name -eq "YOUR_WORKFLOW_NAME" }
Start Workflow
$cnt = 0
foreach($itm in $items)
{
    $workflowInstances = $wfInstanceSevice.EnumerateInstancesForListItem($lst.ID, $itm.ID)
    $clientContext.Load($workflowInstances)
    $clientContext.ExecuteQuery()
    # bypass the item which the workflow instance was started
    $instance = $workflowInstances | Where-Object { $_.WorkflowSubscriptionId -eq  $srb.Id -and $_.Status -ne "Started" }
    if ($instance -ne $null)
    {
        $resultid = $wfInstanceSevice.StartWorkflowOnListItem($srb, $itm.Id, $dictionary)
        $clientContext.ExecuteQuery()
        Write-Host "Started workfkow [" $srb.Name  "] on item ["  $itm.Id  "]: " $resultid.Value -foregroundcolor Green
        Start-Sleep -s 1
        $cnt++
    }
}
Write-Host $cnt " are effected - Done!"
Stop Workflow 
$cnt = 0
foreach($itm in $items)
{
    $workflowInstances = $wfInstanceSevice.EnumerateInstancesForListItem($lst.ID, $itm.ID)
    $clientContext.Load($workflowInstances)
    $clientContext.ExecuteQuery()
    # bypass the item which the workflow instance was started
    $instance = $workflowInstances | Where-Object { $_.WorkflowSubscriptionId -eq  $srb.Id -and $_.Status -eq "Started" }
    if ($instance -ne $null)
        {
            $wfInstanceSevice.CancelWorkflow($instance)
            $clientContext.ExecuteQuery()
            Write-Host "Cancel Workfkow [" $instance.Id  "] on item ["  $itm.Id  "] " $instance.Status -foregroundcolor Red
            $cnt++
            Start-Sleep -s 1
        }
}
Write-Host $cnt " are effected - Done!"
Notes
- Regarding to limitation on SharePoint Online, it only can start 5 workflows instance in a second. So, it should be delayed 1 second for each loop statement.
- Just start a workflow if the workflow instance did not start and stop workflow if the workflow instance is running.
 
 
2 comments:
I know this is an old post but I am so close but I can't get this working.
*I successfully get the items to go thorough but my variable for $wfSubscriptions.Count always comes back as 0 but I have 2 workflows on the list. If you're still monitoring this please suggest what I can try to get this working.
I have the same problem as Douglas
Post a Comment