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);
}
}
}
}
}