Had to call in Microsoft Support to help unlock files that were marked as read-only. Some files appeared to be locked, but using the UI, they couldn’t be unlocked, declared as a record, or edited.
Error: This item cannot be updated because it is locked as read-only
Error: The file “your file string” is checked out for editing by SHAREPOINT\system
This script was setup to run on a SharePoint 2010 instance. If you need to run it on another version, try updating the $sharePointAssembly line.
To unlock a file, input the URL of the file in the line that starts with $fileUrl.
$recordFields =
"_vti_ItemHoldRecordStatus",
"_vti_ItemDeclaredRecord"
$recordProperties =
"ecm_RecordRestrictions",
"ecm_ItemLockHolders",
"ecm_ItemDeleteBlockHolders"
$fileUrl = "http://siteURL/siteCollection/libraryName/folder/subFolder/fileName.pdf"
$sharePointAssembly = [System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
Add-Type -TypeDefinition @"
using Microsoft.SharePoint;
public class EventsDisabler : SPEventReceiverBase
{
public EventsDisabler() {}
public bool EventsDisabled
{
get { return !EventFiringEnabled; }
set { EventFiringEnabled = !value; }
}
}
"@ -ReferencedAssemblies $sharePointAssembly
Write-Host "Getting site collection at $fileUrl..."
[Microsoft.SharePoint.SPSite]$site = New-Object Microsoft.SharePoint.SPSite($fileUrl)
if ($site -eq $null) { exit }
$siteUrl = $site.Url
Write-Host "Found site collection $siteUrl"
Write-Host ""
Write-Host "Getting web at $fileUrl..."
[Microsoft.SharePoint.SPWeb]$web = $site.OpenWeb()
if ($web -eq $null) { exit }
$webTitle = $web.Title
Write-Host "Found web $webTitle"
Write-Host ""
Write-Host "Verifying current user is System Account"
$web.CurrentUser.ID
$site.SystemAccount.ID
if ($web.CurrentUser.ID -ne $site.SystemAccount.ID)
{
Write-Error "Please run this script as System Account" -Category PermissionDenied
#exit
}
Write-Host ""
Write-Host "Getting list at $fileUrl..."
Write-Host $fileUrl
[Microsoft.SharePoint.SPList]$list = $web.GetList($fileUrl)
if ($list -eq $null) { exit }
$listTitle = $list.Title
Write-Host "Found list $listTitle"
Write-Host ""
Write-Host "Getting list item at $fileUrl..."
[Microsoft.SharePoint.SPListItem]$listItem = $web.GetListItem($fileUrl)
if ($listItem -eq $null) { exit }
$listItemName = $listItem.Name
Write-Host "Found list item $listItemName"
Write-Host ""
$eventsDisabler = New-Object EventsDisabler
$eventsOriginallyDisabled = $eventsDisabler.EventsDisabled
if ($eventsOriginallyDisabled -eq $false)
{
Write-Host "Disabling events"
$eventsDisabler.EventsDisabled = $true
Write-Host ""
}
$didWork = $false
$itemNeedsUpdate = $false
#Discard any check-out
if ($listItem.File -ne $null -and $listItem.File.CheckOutType -ne [Microsoft.SharePoint.SPFile+SPCheckOutType]::None)
{
Write-Host "Undoing check-out"
$listItem.File.UndoCheckOut()
$didWork = $true
}
else
{
Write-Host "No file or file is not checked out"
Write-Host ""
}
#Iterate the Record fields and set all values to null
foreach($recordField in $recordFields)
{
if ($listItem.Fields.ContainsField($recordField) -eq $true -and $listItem[$recordField] -ne $null)
{
$recordFieldValue = $listItem[$recordField]
Write-Host "$recordField = $recordFieldValue"
Write-Host "Setting $recordField to null"
$listItem[$recordField] = $null
$didWork = $true
$itemNeedsUpdate = $true
}
}
#Iterate the Record properties and remove any that exist
foreach($recordProperty in $recordProperties)
{
if ($listItem.Properties.ContainsKey($recordProperty) -eq $true)
{
$recordPropertyValue = $listItem.Properties[$recordProperty]
Write-Host "$recordProperty = $recordPropertyValue"
Write-Host "Removing property $recordProperty"
$listItem.Properties.Remove($recordProperty)
$didWork = $true
$itemNeedsUpdate = $true
}
}
#Remove the icon Record lock overlay
if ($listItem.IconOverlay -eq "lockoverlay.png")
{
Write-Host "Removing the icon Record lock overlay"
$listItem.IconOverlay = $null
$didWork = $true
$itemNeedsUpdate = $true
}
if ($didWork -ne $true)
{
Write-Host "No changes were made"
}
Write-Host ""
#Update the item
if ($itemNeedsUpdate -eq $true)
{
Write-Host "Updating item"
$listItem.SystemUpdate()
Write-Host ""
}
if ($eventsOriginallyDisabled -ne $true)
{
Write-Host "Enabling events"
$eventsDisabler.EventsDisabled = $false
Write-Host ""
}
$web.Dispose()
$site.Dispose()