Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Sunday, February 7, 2016

Stop/Start workflow for SharePoint Online using PowerShell Script

With SharePoint Online, PowerShell is as a connected bridge so that it itself brings a big dedication. I always think about PS script whenever get a new request.

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.

Saturday, February 6, 2016

Fix the error "Cannot find an overload for "Load" and the argument count: "1"" in PowerShell

PowerShell script is very useful for end-user who wants to work with behind SharePoint (both of on-premise and online). However, user usually gets some troubles if it throws the error during executing the script. The difficulties of coding and working with PowerShell script is to hard debugging and checking somehow.

This error is an example:  

Cannot find an overload for "Load" and the argument count: "1".

It's so weird because the code is always correct (in developer though). If you know that this error only come from the unique reason so that you have no strange and surprise with the funny mistake.

Here is code:

$web = $clientContext.Web
$clientContext.Load($web)
$clientContext.ExecuteQuery()


$lists = $web.Lists
$clientContext.Load($lists)
$clientContext.ExecuteQuery()


$lst = $list.GetByTitle("CheckList")
$clientContext.Load($lst)
$clientContext.ExecuteQuery()


$qry = New-Object Microsoft.SharePoint.Client.CamlQuery
$qry.ViewXML = "<View><Query><Where><And><Gt><FieldRef Name='Due_x0020_Date'/><Value Type='DateTime'><Today OffsetDays='0'/></Value></Gt><IsNull><FieldRef Name='Actual_x0020_Completion_x0020_Da'/></IsNull></And></Where></Query></View>"


$items = $lst.GetItems($qry)
$clientContext.Load($items)
$clientContext.ExecuteQuery()


Be sure it will happen error when it is executed. The error looks like:

Cannot find an overload for "Load" and the argument count: "1".
At C:\Users\...\Downloads\PSScript\Retrieve.ps1:55 char:1
+ $clientContext.Load($item)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

The root cause of this error come from retrieving the null-able object. That is the variable as a parameter of Load method is null or delivery of that variable is null.

$a = ()
$b = $a.Z()
$c = $b.get_T()
$context.Load($c)

In this example, if $a or $b or $c is null, the error will happen at $context.Load($c) with the message. above.

To fix this, just only take overview of the code and prepare all variables and make sure the name of methods and properties are not miss-spelled and correctly grammar.

Good luck!

Wednesday, November 24, 2010

How to change the limitation of number items in BDC using PowerShell

This is a good link to learn about using PowerShell Mangement (SharePoint Designer) with BDC in SharePoint 2010.

http://blogs.msdn.com/b/bcs/archive/2010/02/16/bcs-powershell-introduction-and-throttle-management.aspx

In Lionelro's topic, he explained and show you what about limitation of number items in BDC when you are using SharePoint Designer and PowerShell. However, I want to show you a short term to change the default limitation using PowerShell.


Start PowerShell Management

Run these scripts:

$dbRule = Get-SPBusinessDataCatalogThrottleConfig -ScopeDatabase -ThrottleType Items -ServiceApplicationProxy$bdcProxy 

#Default and Maximum must be provided together. This increases the limit for external lists to 3000.
Set-SPBusinessDataCatalogThrottleConfig -Identity $dbRule -Maximum 1000000 -Default 3000

Just execute above commands it will change the default limitation of number items when you get the data from BDC.

Good luck.