Introduction

In this tutorial, we will learn about how we can get consolidated workflow reports from the SharePoint Online tenant using PowerShell CSOM and PnP PowerShell. This script will scan through all the sites in a tenant and will export all workflows associated with the lists into a CSV file.

Workflows report from SharePoint Online using PowerShell CSOM & PnP

Using the below PowerShell CSOM & PnP code, we can get all workflows from the SharePoint Online tenant,
  1. Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking
  2. #Load SharePoint CSOM Assemblies
  3. #Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
  4. #Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
  5. cls
  6. $fileName = "Tenant_workflow_Report" #'yyyyMMddhhmm yyyyMMdd
  7. $enddate = (Get-Date).tostring("yyyyMMddhhmmss")
  8. #$filename = $enddate + '_VMReport.doc'
  9. $logFileName = $fileName +"_"+ $enddate+"_Log.txt"
  10. $invocation = (Get-Variable MyInvocation).Value
  11. $directoryPath = Split-Path $invocation.MyCommand.Path
  12. $directoryPathForLog=$directoryPath+"\"+"LogFiles"
  13. if(!(Test-Path -path $directoryPathForLog))
  14. {
  15. New-Item -ItemType directory -Path $directoryPathForLog
  16. #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
  17. }
  18. #$logPath = $directoryPath + "\" + $logFileName
  19. $logPath = $directoryPathForLog + "\" + $logFileName
  20. $isLogFileCreated = $False
  21. #DLL location
  22. $directoryPathForDLL=$directoryPath+"\"+"Dependency Files"
  23. if(!(Test-Path -path $directoryPathForDLL))
  24. {
  25. New-Item -ItemType directory -Path $directoryPathForDLL
  26. #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
  27. }
  28. #DLL location
  29. $clientDLL=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"
  30. $clientDLLRuntime=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"
  31. Add-Type -Path $clientDLL
  32. Add-Type -Path $clientDLLRuntime
  33. #File Download location
  34. $directoryPathForFileDownloadLocation=$directoryPath+"\"+"Download Workflow Details"
  35. if(!(Test-Path -path $directoryPathForFileDownloadLocation))
  36. {
  37. New-Item -ItemType directory -Path $directoryPathForFileDownloadLocation
  38. #Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
  39. }
  40. #File Download location
  41. function Write-Log([string]$logMsg)
  42. {
  43. if(!$isLogFileCreated){
  44. Write-Host "Creating Log File..."
  45. if(!(Test-Path -path $directoryPath))
  46. {
  47. Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
  48. }
  49. else
  50. {
  51. $script:isLogFileCreated = $True
  52. Write-Host "Log File ($logFileName) Created..."
  53. [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)
  54. Add-Content -Path $logPath -Value $logMessage
  55. }
  56. }
  57. else
  58. {
  59. [string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)
  60. Add-Content -Path $logPath -Value $logMessage
  61. }
  62. }
  63. #Object array to hold workflow details.
  64. $WorkflowDetailsForSPOSite=@()
  65. #The below function will read all workflows from a site and return the array output.
  66. Function Get-WorkflowAssociationsDeatilsForEachSiteInTenant()
  67. {
  68. param
  69. (
  70. [Parameter(Mandatory=$true)] [string] $SPOSiteURL,
  71. [Parameter(Mandatory=$true)] [string] $UserName,
  72. [Parameter(Mandatory=$true)] [string] $Password
  73. )
  74. Try
  75. {
  76. $securePassword= $Password | ConvertTo-SecureString -AsPlainText -Force
  77. #Setup the Context
  78. $context = New-Object Microsoft.SharePoint.Client.ClientContext($SPOSiteURL)
  79. $context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $securePassword)
  80. $web = $context.Web
  81. $context.Load($web)
  82. $context.Load($web.Webs)
  83. $context.executeQuery()
  84. #Check if any subsite is available on the site.
  85. if ($web.Webs.Count -ne 0)
  86. {
  87. foreach ($subweb in $web.Webs)
  88. {
  89. Get-WorkflowAssociationsDeatilsForEachSiteInTenant -SPOSiteURL $subweb.url -UserName $userName -Password $password
  90. }
  91. }
  92. #Loading all lists for the particular site.
  93. $context.Load($web.Lists)
  94. $context.ExecuteQuery()
  95. foreach($list in $web.Lists)
  96. {
  97. $context.Load($list.WorkflowAssociations)
  98. $context.ExecuteQuery()
  99. foreach($wfAssociation in $list.WorkflowAssociations)
  100. {
  101. if($wfAssociation.name -notlike "*Previous Version*")
  102. {
  103. $row=new-object PSObject
  104. add-Member -inputObject $row -memberType NoteProperty -name "Site Title" -Value $web.Title
  105. add-Member -inputObject $row -memberType NoteProperty -name "Site URL" -Value $web.Url
  106. add-Member -inputObject $row -memberType NoteProperty -name "List Title" -Value $list.Title
  107. add-Member -inputObject $row -memberType NoteProperty -name "Workflow Name" -Value $wfAssociation.Name
  108. add-Member -inputObject $row -memberType NoteProperty -name "Workflow Type" -Value "SharePoint List"
  109. $WorkflowDetailsForSPOSite+=$row
  110. }
  111. }
  112. }
  113. return $WorkflowDetailsForSPOSite
  114. }
  115. catch
  116. {
  117. write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
  118. $ErrorMessage = $_.Exception.Message +"in exporting workflow details!:"
  119. Write-Host $ErrorMessage -BackgroundColor Red
  120. Write-Log $ErrorMessage
  121. }
  122. }
  123. #Parameters
  124. #$siteURL="https://globalsharepoint2019.sharepoint.com/sites/ModernTeamSiteTestByPnP"
  125. $adminUrl = "https://globalsharepoint2019-admin.sharepoint.com/"
  126. $downloadLocation=$directoryPathForFileDownloadLocation +"\"+ "SPOTenantWorkflowReport.csv"
  127. $userName = "YourSPOUserName"
  128. $password = "YourSPOPassWord"
  129. $securePassword= $password | ConvertTo-SecureString -AsPlainText -Force
  130. #Parameters ends here.
  131. $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
  132. $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $SecurePassword
  133. #Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking
  134. #Retrieve all site collection infos
  135. #Connect-SPOService -Url $AdminUrl -Credential $Credentials
  136. #$sites = Get-SPOSite
  137. Connect-PnPOnline -Url $adminUrl -Credentials $Credentials
  138. $allTenantSites=Get-PnPTenantSite
  139. #Get-WorkflowAssociationsDeatilsForEachSiteInTenant -SPOSiteURL $siteURL -UserName $userName -Password $password | Export-Csv $downloadLocation
  140. if($allTenantSites.Count -gt 0)
  141. {
  142. $finalWorkflowReport =foreach($oneSite in $allTenantSites)
  143. {
  144. Get-WorkflowAssociationsDeatilsForEachSiteInTenant -SPOSiteURL $oneSite.URL -UserName $userName -Password $password
  145. }
  146. $finalWorkflowReport | Export-Csv $downloadLocation -NoTypeInformation
  147. }
  148. Write-host "All workflows have been exported Successfully from the SharePoint Online Tenant." -BackgroundColor Green
Notes about the above code
  • We must use the “Get-PnPTenantSite” to get all sites from the tenant, the other command “Get-PnPSite“, if we use this, it will give only the tenant admin site URL, like below.
Get-PnPSite-in-SharePoint-Online1
  • Similarly, in order to get all sites from the tenant, we can use the “Get-SPOSite” command as well. However, if you have .net framework mismatch version installed in your PowerShell – this command will not work, we will get an error like "Connect-SPOService : Method not found: ‘!!0[] System.Array.Empty()‘"
Get-SPOSite-Error-in-SharePoint-Online2
  • If we use the above code as is this will export all workflows from the tenant. However, if we want to export all workflows from a particular site we can comment the foreach loop and just we need to call the function "Get-WorkflowAssociationsDeatilsForEachSiteInTenant" as below:
  1. Get-WorkflowAssociationsDeatilsForEachSiteInTenant -SPOSiteURL $siteURL -UserName $userName -Password $password | Export-Csv $downloadLocation
Now, let’s execute the above script.
Get-all-workflows-from-SharePoint-Online-Tenant-using-PowerShell-CSOM3
  • After the successful execution of the script, a CSV file with the name of "SPOTenantWorkflowReport.csv" will be created in the script location directory – however, you can change the download location to your desired location.
Get-all-workflows-from-SharePoint-Online-Tenant-using-PowerShell-CSOM4
Now, let’s look at all workflows exported as CSV reports.
CSV-Report-Get-all-workflows-from-SharePoint-Online-Tenant-using-PowerShell-CSOM
We can see in the CSV report, all workflows from the SharePoint Online tenant have been exported.

Prerequisites to execute the above script

You need to place the below two DLLs in your script directory "Dependency Files" folder as like below:
SharePoint Client Dlls

Install PnP PowerShell

To install the "SharePointPnPPowerShellOnline" we need to run the below PowerShell command which will install PowerShell Package Management and then install the PowerShell Modules from the PowerShell Gallery.
  1. (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/sharepoint/PnP-PowerShell/master/Samples/Modules.Install/Install-SharePointPnPPowerShell.ps1')
Change the value of the variables in the parameters section like below.
  1. #Parameters
  2. #$siteURL="https://globalsharepoint2019.sharepoint.com/sites/ModernTeamSiteTestByPnP"
  3. $adminUrl = "Your SPO Admin URL Like - https://globalsharepoint2019-admin.sharepoint.com/"
  4. $downloadLocation=$directoryPathForFileDownloadLocation +"\"+ "SPOTenantWorkflowReport.csv"
  5. $userName = "YourSPOUserName"
  6. $password = "YourSPOPassWord"
  7. $securePassword= $password | ConvertTo-SecureString -AsPlainText -Force
  8. #Parameters ends here.

Summary

In this article, we have learned how we can generate a workflow consolidated report from SharePoint Online tenant using the PowerShell CSOM and PnP.
Download
The above code can be downloaded from here.