(I would have preferred to add this as a comment on the accepted answer, but the code would not have fit.)
I think the following function can eliminate some unnecessary reboots. The PendingFileRenameOperations
registry key supports not only renames, but also deletes (expressed essentially as "rename to null")*. The assumption I am making is that deletes represent pending cleanup operations that will not affect functionality in the meantime.
<#
.SYNOPSIS
Returns true if any true renames-- deletes are ignored-- are present in the
PendingFileRenameOperations registry key.
#>
function Test-PendingFileRename {
[OutputType('bool')]
[CmdletBinding()]
param()
$operations = (Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\').GetValue('PendingFileRenameOperations')
if ($null -eq $operations) {
$false
} else {
$trueOperationsCount = $operations.Length / 2
$trueRenames = [System.Collections.Generic.Dictionary[string, string]]::new($trueOperationsCount)
for ($i = 0; $i -ne $trueOperationsCount; $i++) {
$operationSource = $operations[$i * 2]
$operationDestination = $operations[$i * 2 + 1]
if ($operationDestination.Length -eq 0) {
Write-Verbose "Ignoring pending file delete '$operationSource'"
} else {
Write-Host "Found a true pending file rename (as opposed to delete). Source '$operationSource'; Dest '$operationDestination'"
$trueRenames[$operationSource] = $operationDestination
}
}
$trueRenames.Count -gt 0
}
}
One would implement this in the accepted answer's script by inserting the above function at the top and then replacing the line
if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
with
if (Test-PendingFileRename) { return $true }
* refs: