Originally this script was built to audit a library for problematic workflows. I re-purposed it to also decare records which weren’t previously declared. Modify it to serve your purpose.
Add-PSSnapin Microsoft.SharePoint.PowerShell function Write-Success { process { Write-Host $_ -ForegroundColor Green } } $config = (Get-Content config.json) -join "`n" | ConvertFrom-Json $SPWeb = Get-SPWeb $config.SPSite; $listName = "MyLibraryWithProblem"; $hitlist = @(); $count = $SPWeb.Lists[$listName].items.count; $i=1; foreach($item in $SPWeb.Lists[$listName].items) { # | select -First 200) { $target = @{}; $target.ID = $item.ID; $target.IsRecord = [Microsoft.Office.RecordsManagement.RecordsRepository.Records]::IsRecord($item); $target.Title = $item["Title"]; $target.Created = $item["Created"].ToString("s"); # $item; if($item.Workflows.count -gt 0) { $workflows = @(); foreach($workflow in $item.Workflows) { $wfinstance = @{}; $wfinstance.InstanceId = $workflow.InstanceId; $wfinstance.Modified = $workflow.Modified.ToString("s"); $wfinstance.StatusText = $workflow.StatusText; $wfinstance.IsCompleted = $workflow.IsCompleted; $wfinstance.StatusUrl = $workflow.StatusUrl; $workflows += $wfinstance; } $target.Workflows = $workflows; } #determine if we should ignore this entry $ignore = $true; try { if($target.Workflows.count -gt 0) { foreach($wf in $target.Workflows) { if($wf.IsCompleted -ne $true) { $ignore = $false; } if($wf.StatusText -ne "Approved") { #$item.Workflows; $ignore = $false; } #not sure why but my system shows a typo for cancelled state if($wf.StatusText -eq "Canceled") { $ignore = $true; } } } } catch {}; if(!$target.IsRecord) { $ignore = $false; } if($item["Created"] -gt (get-date).AddDays(-14)) { $ignore = $true; } if(!$ignore) { $hitlist += $target; } $i++; Write-Progress -Activity "Collecting data" -status $target.Title -percentComplete ($i / $count*100); } #$hitlist | ConvertTo-Json -Depth 10 #from this list let's either: # decare as record when it's not # and cancel a workflow when it's still running # noting that we are only interested in the items created past 14 days ago $count = $hitlist.count; $i=0; foreach($target in $hitlist) { $i++; Write-Progress -Activity "Working through list" -status $target.Title -percentComplete ($i / $count*100); if(!$target.IsRecord) { $item = $SPWeb.Lists[$listName].items.GetItemById($target.ID); Write-Output "Declaring as record for $($target.Title)" | Write-Success; if($item.File.CheckOutStatus -ne "None") { Write-Output " Checking in file first because it is checked out" | Write-Success; $item.File.CheckIn("Automatic CheckIn. (Administrator)"); } [Microsoft.Office.RecordsManagement.RecordsRepository.Records]::DeclareItemAsRecord($item); } foreach($wf in $target.Workflows) { if(!$wf.IsCompleted) { $item = $SPWeb.Lists[$listName].items.GetItemById($target.ID); foreach($wfi in $item.Workflows) { if($wfi.InstanceId -eq $wf.InstanceId) { Write-Output "Cancelling workflow for $($target.Title)" | Write-Success; [Microsoft.SharePoint.Workflow.SPWorkflowManager]::CancelWorkflow($wfi); } } } } }