Recently one of our users complained, that he can not open an Excel document for editing from a SharePoint document library, as he gets a warning that the file is locked by himself. It should be a known issue, as documented here, however in our case it did not help waiting 10 minutes, or even hours. I check the AllDocs table in the content database, and found very strange values in the record corresponding to the locked document (filtered for DirName and LeafName fields). The document was really locked by the complaining user (CheckoutUserId field), the CheckoutDate field contained the current time, and (that was the surprise) the CheckoutExpires field contained a date value that was about 2-3 month before the current date.
Although one could delete the dirty data from the database, as shown for example in this article or in this post, that would be an unsupported solution, so I wanted to find an officially acceptable way. The information I found in this post was closer to my expectations.
As I checked the status of the file from PowerShell I get an output similar to the screenshot below, that suggests that the file is not locked:
$web = Get-SPWeb http://intranet.contoso.com
$list = $web.Lists["DocLib"]
$item = $list.GetItemById(2)
$file = $item.File
$file
It could be a reason, why SharePoint does not try to delete the lock, although I found it still rather odd.
As I tried to call the ReleaseLock method on the $file I got an error stating that the file is not locked. What helped in this case was not less surprising as the former situation. I checked out the file and then made an undo for the checkout:
$ft = New-Object System.TimeSpan(10000)
$file.Lock([Microsoft.SharePoint.SPFile+SPLockType]::Exclusive, "test lock", $ft)
$file.UndoCheckOut()
After this the lock status of the file was cleared in the database as well.
If the file happened to be locked by a user other than the current user, and we would like to release the lock, we get an error message stating that the file is locked by an other user. However, there is a way to release the lock even in this case using PowerShell and that is possible via impersonating the user that holds the lock:
$web = Get-SPWeb http://intranet.contoso.com
$list = $web.Lists["DocLib"]
$item = $list.GetItemById(2)
$file = $item.File
$userId = $file.LockedByUser.ID
$user = $web.AllUsers.GetByID($userId)
$impSite= New-Object Microsoft.SharePoint.SPSite($web.Url, $user.UserToken);
$impWeb = $impSite.OpenWeb();
$impList = $impWeb.Lists[$list.Title]
$impItem = $impList.GetItemById($item.ID)
$impFile = $impItem.File
$impFile.ReleaseLock($impFile.LockId)
