Background

Your organisation is using SharePoint as a collaboration and productivity platform, and your business units have built their solutions on it. As part of business solutions, IT teams have built workflows using SharePoint designer to cater business needs. One of the challenges developers or IT professionals used to have is how to export and import this workflow to other SharePoint sites in case if you are having multiple environments like Dev, Test, UAT and Prod.

In today’s blog post, we will go through it and use PowerShell to export and import workflows across different site collections/tenants.

Solution

PowerShell will come to rescue while dealing with such problems,  scripts listed below will help you in doing that task. It is using commands from PnP-PowerShell as well.

You need to export the workflow definition that you have built using SharePoint Designer in your existing site collection. It relies on parameters like URL, Application Client ID, Application Client Secret and Workflow name to connect to SharePoint and extract workflow definition from it and then writes it into a XAML file.

Export.ps1

[CmdletBinding(SupportsShouldProcess = $true)]
param (
    $Url,
    $ClientId,
    $ClientSecret,
	$WFDefinitionName
)

# include the common script
. "$PSScriptRoot\Common.ps1"

$FilePath = "$PSScriptRoot\WorkFlowDefinition\$($WFDefinitionName).xaml"

Connect-PnPOnline -Url $Url -AppId $ClientId -AppSecret $ClientSecret

Write-Host " "
Write-Host "Connected successfully to: $($Url)" -ForegroundColor Yellow

Get-PnPWorkflowDefinition -Name $WFDefinitionName
<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>
Save-WorkflowDefinition (Get-PnPContext) $WFDefinitionName $FilePath

Once you have successfully exported workflow definition, you need to import it into the destination site. Import function relies on parameters like URL, Application Client ID, Application Client Secret and Workflow name to connect to SharePoint and import workflow definition from the file and then updates it into SharePoint site.

Import.ps1

[CmdletBinding(SupportsShouldProcess = $true)]
param (
    $Url,
    $ClientId,
    $ClientSecret,
    $WFDefinitionName
)

# include the common script
. "$PSScriptRoot\Common.ps1"

$FilePath = "$PSScriptRoot\WorkFlowDefinition\$($WFDefinitionName).xaml"

Connect-PnPOnline -Url $Url -AppId $ClientId -AppSecret $ClientSecret

Write-Host " "
Write-Host "Connected successfully to: $($Url)" -ForegroundColor Yellow

$ctx = Get-PnPContext
$parentContentTypeId = $null

$wf = Get-PnPWorkflowDefinition -Name $WFDefinitionName

if ($wf -eq $null)
{
    # Load workflow definition
    Publish-WorkflowDefinition (Get-PnPContext) $FilePath $WFDefinitionName

    Add-PnPWorkflowSubscription -Name $WFDefinitionName -DefinitionName $WFDefinitionName -List "YourSharePointListName" -HistoryListName "Workflow History" -TaskListName "Workflow Tasks" -StartOnCreated
}
else
{
    Write-Host "Workflow definition $($WFDefinitionName) already exists.." -ForegroundColor Yellow
}

Above two import and export commands rely on some PowerShell functions and are references in Common.ps1 and are listed below:

Common.ps1

function Save-WorkflowDefinition($ctx, $wfName, $filePath) {
    $web = $ctx.Web   

    $wfm = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager -ArgumentList $ctx, $web
    $wfds = $wfm.GetWorkflowDeploymentService()
    $wfdefs = $wfds.EnumerateDefinitions($false)
    $ctx.Load($wfdefs);
    $ctx.ExecuteQuery();

    $wdef = $wfdefs | Where-Object {$_.DisplayName -eq $wfName}

    if (!$wdef) {
        Write-Error "Could not find Workflow definition to Export";
        return;
    } 

    $wdef | Export-Clixml $filePath

	Write-Host " "
    Write-Host "Workflow definition '$($wfName)' exported successfully.." -ForegroundColor Green
}

function Publish-WorkflowDefinition($ctx, $filePath, $wfName) {
    $ctx = Get-PnPContext
    $web = $ctx.Web

    Write-Host " "
	Write-Host "Loading Workflow definition: $($filePath)"

    $wfLoadedDefinition = Import-Clixml $filePath
    $wfDefinition = Get-PnPWorkflowDefinition -Name $wfName 

    if ($wfDefinition) {
		Write-Host "Updating existing workflow definition for $($wfName)"
    }
    else {
        Write-Host "Creating new workflow definition: $($wfName)"
        $wfDefinition = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition -ArgumentList $ctx
    }

    $xamlActivity = $wfLoadedDefinition.Xaml;

    $wfDefinition.DisplayName = $wfLoadedDefinition.DisplayName;
    $wfDefinition.Description = $wfLoadedDefinition.Description;
    $wfDefinition.Xaml = $xamlActivity;
    $wfDefinition.FormField = $wfLoadedDefinition.FormField;
    $wfDefinition.SetProperty("ContentTypeId", $wfLoadedDefinition.Properties["ContentTypeId"]);
    $wfDefinition.SetProperty("FormField", $wfLoadedDefinition.Properties["FormField"]);
    $wfDefinition.RequiresAssociationForm = $wfLoadedDefinition.RequiresAssociationForm;
    $wfDefinition.RequiresInitiationForm = $wfLoadedDefinition.RequiresInitiationForm;
    $wfDefinition.RestrictToType = $wfLoadedDefinition.RestrictToType;

    $wfm = New-Object Microsoft.SharePoint.Client.WorkflowServices.WorkflowServicesManager -ArgumentList $ctx, $web
    $wfDeploymentService = $wfm.GetWorkflowDeploymentService()
    $definitionId = $wfDeploymentService.SaveDefinition($wfDefinition)
    $ctx.Load($wfDefinition)
    $ctx.ExecuteQuery()

    Write-Host "Workflow definition saved successfully for workflow: $($wfName)"

    $wfDeploymentService.PublishDefinition($definitionId.Value)
    $ctx.Load($wfDefinition)
    $ctx.ExecuteQuery()

    Write-Host " "
    Write-Host "Workflow definition '$($wfName)' published successfully.." -ForegroundColor Green
}

I hope above set of scripts will help some of you to take SPD workflows around and deploy it across multiple development sites, test sites and/or UAT sites.

Category:
Office 365, PowerShell, SharePoint

Join the conversation! 1 Comment

  1. […] Export/Import SharePoint Designer Workflows using PowerShell […]

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: