Why can't I delete a file because it is in use on Windows?
A file refuses to delete because another program holds it open. Confirm the lock, find the owner, close it, then remove the file for good.
What this covers
Windows blocks deletion while any process holds a handle to the file — a half-open Excel workbook, a paused OneDrive sync, a media player, or an antivirus scan. This guide walks from confirming the lock to removing the file, and covers the two cases that masquerade as a lock: a network share opened on another PC, and NTFS permissions.
Symptom
Confirm the file is really locked
Attempt to open the file with an exclusive handle that allows no sharing. If the open succeeds, nothing has it locked — your failure is permissions or path related, so skip the process hunting and check the ACL instead. If it throws a sharing-violation error, another process holds the handle, and you can continue.
Test whether another program is holding a file open by attempting an exclusive .NET File.Open inside try/catch.
$ try {
$fs = [System.IO.File]::Open('C:\Temp\report.xlsx', 'Open', 'ReadWrite', 'None')
$fs.Close(); 'File is NOT locked'
} catch { 'File IS locked: ' + $_.Exception.Message }Spot the app that probably holds the file
List running processes with their memory footprint and look for the usual suspects: Office apps, PDF readers, media players, sync clients (OneDrive, Dropbox), backup tools and Explorer itself. Note the name and PID of the one that plausibly opened the file — you need that identifier for the next step. Memory size is a hint, not proof: a 30 MB Word process can hold a 2 GB document just fine.
Rank running processes by working-set memory and CPU time in one PowerShell pipeline.
$ Get-Process | Sort-Object WS -Descending | Select-Object -First 15 Name, Id, @{n='Mem(MB)';e={[math]::Round($_.WS/1MB,1)}}, @{n='CPU(s)';e={[math]::Round($_.CPU,1)}} | Format-Table -AutoSizeRule out another computer holding it over a share
If the file lives in a shared folder, the handle can belong to someone else on the network: they opened it and left it open. This lists every file currently opened on your shares and lets you cut the offending session by its ID. It only returns rows when file sharing and the objects list are enabled, so an empty result on a home PC is normal and not a dead end.
List every file that other computers on the network have opened on your shared folders with openfiles /query, and cut a session with /disconnect.
$ openfiles /query /fo table
# disconnect a specific open file by ID:
openfiles /disconnect /id 1234Rule out a permissions problem in disguise
An Access Denied error on delete often reads to users like 'in use'. Dump the file's ACL to see who owns it and what your account is allowed to do. If your account only has Read, or the file is owned by SYSTEM from an installer, no amount of closing processes will help — you need to take ownership or grant write and delete rights first.
Dump the ACL of any file or folder with icacls, then grant, deny or reset permissions with inheritance control.
$ icacls "D:\Data"Close the process that holds the file
End the offending process by image name or by the PID you identified. Use the non-forced form first so the app can prompt to save; add the forced switch only when it refuses to quit, since that discards unsaved work. Close the whole application rather than an individual window — a background window in the same process still holds the handle.
End an unresponsive application from Command Prompt using taskkill by image name or PID.
$ taskkill /IM notepad.exe /F :: or by process id: taskkill /PID 12345 /FDelete the file to the Recycle Bin
Remove the file with a recycle-bin delete, so a mistake stays recoverable. This works for a single file or a whole directory. If deletion still fails here, a handle was re-taken between the two steps — re-run the exclusive-open test and repeat the process hunt rather than reaching for a permanent delete.
Use Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile/DeleteDirectory with SendToRecycleBin for recoverable deletes in scripts.
$ Add-Type -AssemblyName Microsoft.VisualBasic
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile('C:\Temp\old.txt', 'OnlyErrorDialogs', 'SendToRecycleBin')Verify the file is gone
Check whether the path still exists. A false result confirms the file was really removed and no process recreated it. If it is still true, something is recreating or re-locking the file — a running sync client that restores it, or an app that reopens the path on a timer — and that process, not the file, is the real problem.
The PowerShell true/false existence test every script should start with — supports files, folders, registry keys, and wildcards.
$ Test-Path 'C:\Program Files\Git\bin\git.exe'How to confirm it worked
The file no longer appears in Explorer, and a path existence test returns false for its location.
Sources
- FileStream ClassEvidence: FileStream with FileShare.None throws IOException when the file is already open elsewhere, the mechanism behind the lock test.
- File.Open(String, FileMode, FileAccess, FileShare) MethodEvidence: File.Open with FileShare.None throws IOException when another process holds the file open, which is the basis of the lock test.
- Get-Process - SS64Evidence: Shows sorting processes by working set and other memory-oriented examples.
- Get-ProcessEvidence: Documents Get-Process objects and their WS and CPU properties.
- Openfiles - List or Disconnect Open Files - SS64Evidence: Documents /query listing remotely opened files and /disconnect closing them by ID or name.
- openfiles command | Microsoft LearnEvidence: openfiles /query lists files opened from the local system by remote users; openfiles /disconnect /id <id> disconnects a specific open file.
- ICACLS - Windows CMDEvidence: SS64 details icacls syntax for /grant, /deny, /remove and the inheritance rights letters (OI, CI, IO, NP) used in ACE entries.
- icacls | Microsoft LearnEvidence: Microsoft documents icacls for displaying and modifying discretionary access control lists (DACLs), including /grant with inheritance flags like (OI)(CI).
Last verified: 2026-09-22
Related guides
Diagnose which processes and services are consuming your RAM on Windows, and verify the fix from the command line.
Work through repeating System and Application errors in the right order: query the log properly, look at the other places errors hide, then confirm the noise actually stops.
Use forfiles to preview old files, clear %TEMP% with PowerShell, and confirm space is back with Disk Cleanup.