#Requires -Version 5.1 <# JbTecWiz Support Centre -- generated fix script Fault : A file is locked open by a user who has gone home Fix : Find and close the handle Source: https://jbtecwiz.com/support/srv-sto-fileserver-locks Run as : Elevated PowerShell on the file server Expect : 15 minutes Risk : medium Reversible : yes WHEN THIS IS THE RIGHT FIX A specific file is locked. HOW TO UNDO IT None -- the handle is gone. Any unsaved work in that session is lost, which is why the idle check matters. This script walks the fix one step at a time and asks before each one. Steps with no command are things you do yourself -- it prints those and waits. Run with -DryRun to print without executing. -------------------------------------------------------------------- NO WARRANTY - USE AT YOUR OWN RISK This script is provided by JbTecWiz as-is and with no warranty of any kind, express or implied. You run it entirely at your own risk. JbTecWiz accepts no liability for any loss or damage arising from its use, including but not limited to data loss, downtime, or configuration changes that turn out to be wrong for your system. You are responsible for reading this script before running it, for satisfying yourself that it suits the machine in front of you, and for having a working backup first. Some steps cannot be undone. -------------------------------------------------------------------- #> [CmdletBinding()] param( # Print every step and command without running anything. [switch]$DryRun, # Do not ask before each step. Read the script first if you use this. [switch]$Unattended ) $ErrorActionPreference = 'Stop' $script:Failed = 0 function Write-Rule { param([string]$Text) Write-Host '' Write-Host ('-' * 70) -ForegroundColor DarkGray if ($Text) { Write-Host $Text -ForegroundColor Cyan } } function Show-Prose { param([string]$Text, [string]$Colour = "Gray") if (-not $Text) { return } $words = $Text -split "\s+"; $line = " " foreach ($w in $words) { if (($line.Length + $w.Length) -gt 74) { Write-Host $line -ForegroundColor $Colour; $line = " " } $line += "$w " } if ($line.Trim()) { Write-Host $line -ForegroundColor $Colour } } function Invoke-Step { param( [int]$Number, [string]$Do, [string]$Why, [scriptblock]$Command, [switch]$Manual, [string]$Shell = "powershell" ) Write-Rule " Step $Number of 6" Show-Prose $Do "White" if ($Why) { Write-Host ""; Show-Prose $Why "DarkGray" } if ($Manual) { Write-Host '' Write-Host ' -> Do this yourself, then press Enter to carry on.' -ForegroundColor Yellow if (-not $Unattended -and -not $DryRun) { [void](Read-Host) } return } Write-Host '' foreach ($l in ($Command.ToString().Trim() -split "`n")) { Write-Host (" " + $l.Trim()) -ForegroundColor Green } Write-Host '' if ($DryRun) { Write-Host " (dry run -- not executed)" -ForegroundColor DarkGray; return } if (-not $Unattended) { $a = Read-Host " Run this step? [Y]es / [S]kip / [Q]uit" if ($a -match "^[Qq]") { Write-Host " Stopped at your request."; exit 0 } if ($a -match "^[Ss]") { Write-Host " Skipped." -ForegroundColor DarkGray; return } } try { & $Command } catch { $script:Failed++ Write-Host (" Step $Number failed: " + $_.Exception.Message) -ForegroundColor Red Show-Prose "The rest of the fix may depend on this. Read the write-up before carrying on." "Red" if (-not $Unattended) { $c = Read-Host " Carry on anyway? [y/N]" if ($c -notmatch "^[Yy]") { exit 1 } } } } Write-Rule Write-Host ' A file is locked open by a user who has gone home' -ForegroundColor White Write-Host ' Find and close the handle' -ForegroundColor Cyan Write-Host '' Write-Host ' Risk: medium Reversible 15 minutes' Write-Host '' Show-Prose 'No warranty. Use at your own risk - JbTecWiz accepts no liability. Read it before you run it, and have a backup.' 'DarkYellow' Write-Rule if (-not $Unattended -and -not $DryRun) { $go = Read-Host ' Ready? [y/N]' if ($go -notmatch "^[Yy]") { Write-Host " Nothing was changed."; exit 0 } } Invoke-Step -Number 1 -Do 'Find the open handle and who holds it.' -Command { Get-SmbOpenFile | Where-Object Path -like '*budget*' | Format-Table SessionId,ClientComputerName,ClientUserName,Path -AutoSize } Invoke-Step -Number 2 -Do 'Check whether the user is genuinely gone before closing it -- closing a handle on a file somebody is actively editing loses their unsaved work.' -Why 'The SecondsIdle figure is the deciding number. A session idle for hours is safe to close; one idle for seconds belongs to someone typing into the document right now.' -Command { Get-SmbSession | Where-Object ClientUserName -like '*jbloggs*' | Format-Table ClientComputerName,ClientUserName,NumOpens,SecondsIdle } Invoke-Step -Number 3 -Do 'Close the specific handle.' -Command { Get-SmbOpenFile | Where-Object Path -like '*budget*' | Close-SmbOpenFile -Force } Invoke-Step -Number 4 -Do 'If the lock persists, close the whole session for that machine.' -Command { Get-SmbSession -ClientComputerName WS042 | Close-SmbSession -Force } Invoke-Step -Number 5 -Do 'For Office files, check for an orphaned owner file, which keeps the lock message appearing even after the handle is gone.' -Command { Get-ChildItem '\\fs01\share' -Recurse -Force -Filter '~$*' -ErrorAction SilentlyContinue | Format-Table FullName,LastWriteTime } Invoke-Step -Number 6 -Do 'If this happens frequently to the same share, look at whether the clients are losing connectivity -- repeated orphaned locks are a network symptom, not a file server one.' -Manual Write-Rule " Confirm it worked" Show-Prose 'The file opens for editing and no handle remains.' 'White' Write-Host '' if (-not $DryRun) { Get-SmbOpenFile | Where-Object Path -like '*budget*' } Write-Rule if ($script:Failed -gt 0) { Write-Host (" Finished with " + $script:Failed + " failed step(s).") -ForegroundColor Yellow Show-Prose 'Read the full write-up at https://jbtecwiz.com/support/srv-sto-fileserver-locks' 'Yellow' } else { Write-Host ' Finished.' -ForegroundColor Green } Write-Host '' Show-Prose 'To undo: None -- the handle is gone. Any unsaved work in that session is lost, which is why the idle check matters.' 'DarkGray' Write-Rule