20

I was wondering if there is a command-line tool that allows me to close all file handles that are open under a specific folder.

I have tried ProcessExplorer, Unlocker and similar tools, but they offer a GUI interface, and are not useful in a programming environment

A solution on Python, cmd or PowerShell would be ideal.

2
  • Remember that forcibly closing a file handle might cause the program using that handle to crash. Sep 15 '11 at 3:02
  • 1
    @HarryJohnston Worse, you could end up causing all sorts of file corruption for as long as the program is open: technet.microsoft.com/en-us/magazine/…
    – Bob
    Jul 27 '14 at 6:42
6

Unlocker does claim it gives you this ability:

  1. Simply right click the folder or file and select Unlocker

    Step1

  2. If the folder or file is locked, a window listing of lockers will appear

    Step2

  3. Simply click Unlock All and you are done!

I'm not sure if it supports command-line usage.

MalwareByte's FileAssassin performs similar actions, and does support command-line usage, so you should be able to script it pretty easily.

FileAssassin's Switches

3
  • Thanks techie007, I guess I missed that. I noticed that Unlocker sometimes misses my files (ProcessExplorer doesn't).. A second issue is if I want unlock or release files programatically (e.g. a command line tool would help along this direction). Sep 13 '11 at 19:27
  • @intrpc There ya go, I added another (command-line-friendly) suggestion. :) Sep 13 '11 at 19:49
  • 1
    Careful, Unlocker comes bundled with malware these days. Jan 24 '17 at 19:17
11

Thanks for this. We've been having some issues with open file handles causing git checkouts to fail within our Windows-based Jenkins jobs and this helped correct the problem handily. I'll throw out the basics of the technique:

  1. Install Handle.exe on the build node. I downloaded it from here http://technet.microsoft.com/en-us/sysinternals/bb896655, unzipped it and dropped Handle.exe under C:\Windows\System32 to ensure it would be available on the default %PATH%

  2. Install the Jenkins pre-scm-buildstep plugin: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep. This allows us to define operations before the git plugin started reaching for potentially locked files.

  3. Implemented the following batch command as a pre-scm build step:

    @echo off
    echo Cleaning up open file handles from %NODE_NAME%:%WORKSPACE%...
    for /f "tokens=3,6,8 delims=: " %%i in ('Handle /accepteula %WORKSPACE% ^| grep workspace') do echo Releasing file lock on E:%%k & handle -c %%j -y -p %%i
    

It appears to work nicely and definitely cuts down on spurious failures. I'll also note a couple gotchas I worked through:

  • Handler.exe has an EULA that must be accepted the first time it runs. If you're running your Jenkins agent as a service under the Local System context, this is problematic because you can't log in as that user and accept it by hand. When we tried running it from the Jenkins job, the process just hung waiting for user input and it took a few minutes to figure out why. I solved this by running it from the Jenkins job using the /accepteula flag and I recommend anyone implementing this as an automated process do the same. This happens to be a registry setting under HKEY_CURRENT_USER\Software\Sysinternals\Handle and you can also set and unset it via regedit.exe if you need to manipulate it for a specific user, but the command line option seemed easiest.

  • The Jenkins Batch step plugin executes batch code as if it were in a script rather than as a command line directive. Notice the escapes ( e.g. %%i, ^| ).

Thanks!

3
  • Struggling to get the syntax of this, can somebody provide more detail into what's %%i,j etc ?
    – c4sh
    Feb 28 '19 at 12:42
  • This might help to understand the syntax of the batch command: robvanderwoude.com/ntfortokens.php
    – c4sh
    Feb 28 '19 at 14:52
  • 1
    How did you guys solve the fact that handle.exe needs to run as administrator, while we run it from a Jenkins user that isn't admin?
    – c4sh
    Mar 5 '19 at 16:10
9

We use the following snippet to close file handle from users to our server. You may be able to modify it for your use.

rem close all network files that are locked
for /f "skip=4 tokens=1" %%a in ('net files') do net files %%a /close
1
  • Thanks @Brendan. I think your code was not formatted properly. Your answer looks interesting, so if you don't mind editing it, I would suggest that you select your lines of code, and then click the button with the two curly bracelets. That will turn your snippet into readable code. Sep 13 '11 at 21:22
6

I create this little batch file to auto release all locks to xml file by my eclipse

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\ ^| grep .xml') do echo Releasing %%k & handle -c %%j -y -p %%i

You need to download the handle utility from Microsoft site and grep utility from GnuWin32

If you don't need filter by file type, you can skip grep part like this:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Or if you don't need to filter locks by a particular program, just remove the eclipse process filter:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Remember to replace e:\git\ with your folder path.

5

If you're using PSTools, this will force close all open files recursively:

psfile \\serverName c:\path\toDatabase\ -c

Note that c:\path\toDatabase\ is the C: drive on \\serverName, not your local machine. This was unclear to me at first so I thought I'd point it out.

This is a brute force approach that's almost guaranteed to lose data, so use it with caution.

We have a badly cobbled together Access database that literally brings our company to it's knees on a regular basis (I had to fix it three times just yesterday).

The guy who normally handles this is on vacation for a couple of weeks and his instructions use a UI based approach (Start > Computer > Manage > Computer Management (Local) > Connect to another computer > System Tools > Shared Folders > Open Files > Close Open Files). WAY too many clicks when I can just run the above command & kick the entire company out of all the database files & start the Compact & Repair process (which I'm also working on a brute force scripted approach to).

The trick is staying ahead of the folks who immediately start to reconnect to the database as soon as it goes down. They're so used to this that it doesn't occur to them to file a bug against it, they just keep hammering the database until they get back in. I just keep booting them off until I've compacted & repaired the three dozen files that make up the database.

5

If you're talking about files handles open via an SMB share on a Windows file server (Server 2012 or newer), here's the PowerShell answer:

Get-SmbOpenFile | Where-Object { $_.Path -like "D:\Folder\*" } | Close-SmbOpenFile -Force

On an older Windows file server, it's openfiles.exe /disconnect.

For a local system file handle, the best way I've found is to use Sysinternals handle.exe

3

I prefer http://lockhunter.com because it supports both GUI and command line interface, and in many cases was able to delete files that could not be deleted by Unlocker.

2

Unlocker can run in silent mode as well.

For example, to unlock all files inside Jenkins workspace:

"C:\Program Files\Unlocker\unlocker.exe" "%WORKSPACE%" /S

Then you can safely delete workspace files:

del "%WORKSPACE%\*.*" /s /q
0

You can use Powershell to do this stuff:

function KillProcessesWithHandles
{
    param([string]$path)

    $allProcesses = Get-Process

    # Start by closing all notepad processes. Someone may have left a logor config file open
    $allProcesses | Where-Object {$_.Name -eq "notepad"} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Then close all processes running inside the folder we are trying to delete
    $allProcesses | Where-Object {$_.Path -like ($path + "*")} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Finally close all processes with modules loaded from folder we are trying to delete
    foreach($lockedFile in Get-ChildItem -Path $path -Include * -Recurse) {
        foreach ($process in $allProcesses) {
            $process.Modules | Where-Object {$_.FileName -eq $lockedFile} | Stop-Process -Force -ErrorAction SilentlyContinue
        }
    }
}

For more details, Refer Thomas Ardal here: https://thomasardal.com/deleting-contents-of-a-folder-containing-files-with-open-file-handles-using-powershell/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.