0

I would like to close the handles of all processes that access a certain file. To retrieve the processes, I use the solution of Eric J. in this thread. Now, unfortunately, it does not work to close the Process.Handle with the Winapi function CloseHandle(). The Process class returns the correct pid, but not the correct handle.

This can also be seen when using Handle from Mark Russinovich. This returns a different handle, which you can actually close with the given function.

So, can I get the file locking handle from the Process class? And if not, which Winapi should I use for it?

(Working) Handle by Mark Russinovich:

C:\dev\Handles\Handle>handle.exe C:\dev\Handles\test.accdb

MSACCESS.EXE       pid: 5952   type: File           EA4: C:\dev\Handles\test.accdb

Process Handle:

List<Process> LockingProcesses = FileUtil.WhoIsLocking(@"C:\dev\Handles\test.accdb");
foreach (Process process in LockingProcesses)
{
    CloseHandle(process.Handle);
}

image

Solution (credit to Remy Lebeau):

Handle.exe is reporting the actual file handle within the target process. Process.Handle returns the process handle of the EXE file that created the process which FileUtil.WhoIsLocking() says has the target file open. Two completely different things, which is why they are different values.

See How can I close a handle in another process? for a detailed explanation of how to find and close handles in other processes, similar to how SysInternals Process Explorer does.

Jachuc
  • 27
  • 8
  • 1
    You're better off using a database that was designed for simultaneous multiple users. For example, you may see if [SQL Server Express](https://www.microsoft.com/en-us/sql-server/sql-server-downloads) meets your needs. – Tu deschizi eu inchid Dec 16 '21 at 16:13
  • I wish it was up to me which database we use.... – Jachuc Dec 16 '21 at 16:14
  • 1
    `CloseHandle` doesn't terminate a a process. It simply releases your access to the object, like calling `IUnknown::Release()` on a COM object. `Process` has a `Kill` method, though. Also, handles can be different in different processes because each process has its own data structure allocated to refer to that object and the handle value is a pointer to that object in that process's memory space. – madreflection Dec 16 '21 at 16:14
  • You may need to re-evaluate the code that accesses the database. The connection shouldn't remain open for any longer than is needed to perform the desired operation. – Tu deschizi eu inchid Dec 16 '21 at 16:16
  • @madreflection: I don't want to terminate or kill the process, but close the handle. (just as with Handle by Russinovich only programmatically). – Jachuc Dec 16 '21 at 16:16
  • @user9938: Let's just assume that I don't have access to that code. – Jachuc Dec 16 '21 at 16:18
  • 1
    You don't have access to the *file* handle in that process that holds the file open. If you could, you would have to inject code into that process to close the handle, and then the process would fail in all sorts of strange ways when its file handle is no longer valid. At that point, you're better off terminating the process. – madreflection Dec 16 '21 at 16:20
  • Then you should talk to the person who does and ask him/her to fix the code. Externally closing a file handle (or killing the process) is likely to lead to issues. – Tu deschizi eu inchid Dec 16 '21 at 16:20
  • For clarity, I am well aware of the risks and the potential consequences. And obviously you can detect and close the handle that keeps the file open. The only question is how. – Jachuc Dec 16 '21 at 16:26
  • You're still failing to grasp a fundamental concept here: A handle is just a reference to a (kernel) object. The object gets destroyed only after the final handle to it gets closed. Different handles can refer to the same object. You would have to walk through the target processes' handle tables, and close each and every handle referencing the kernel object in question. Calling `CloseHandle` on the process handle that happens to own a handle to the actual kernel object does nothing towards that goal. – IInspectable Dec 16 '21 at 17:04
  • Thank you for the detailed explanation. This raises several questions for me. The most important of them is how do I get the table of all process handlers? – Jachuc Dec 16 '21 at 17:25
  • 1
    Arguably, the most important question you should be asking is: What are the *real* consequences of doing this? – IInspectable Dec 16 '21 at 18:13
  • 1
    for close file in remote process you need use `DuplicateHandle` with `DUPLICATE_CLOSE_SOURCE` instead `CloseHandle`. then file handle can not exist at all, but created section on file, which hold file. on this already all - game is over. not exist solution – RbMm Dec 16 '21 at 19:34
  • "*The `Process` class returns the correct pid, but not the correct handle... [`Handle` from Mark Russinovich] returns a different handle, which you can actually close with the given function*" - `Handle.exe` is reporting the actual *file* handle within the target process. `Process.Handle` returns the *process* handle of the EXE file that created the process which `FileUtil.WhoIsLocking()` says has the target file open. Two completely different things, which is why they are different values. – Remy Lebeau Dec 16 '21 at 21:49
  • 2
    See [How can I close a handle in another process?](https://scorpiosoftware.net/2020/03/15/how-can-i-close-a-handle-in-another-process/) for a detailed explanation of how to find and close handles in other processes, similar to how [SysInternals Process Explorer](https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer) does. – Remy Lebeau Dec 16 '21 at 21:50
  • Thank you Remy. This is the answer I was looking for. – Jachuc Dec 17 '21 at 11:12
  • @Jachuc - solution for this not exist. at first and main - file handle can not exist at all. possible open file, create section on it, and close handle. mapped section effective lock file from modification. but no handle. possible enumerate all handles in system. if exist permission for open target process - duplicate file handle and query it volume/id for check - are this is target file and than try close it. but here again exist raise - instead target file, you can close already something else. and even if close exactly target file - process can became unstable after this. so all is wrong – RbMm Dec 17 '21 at 11:25
  • @RbMm I am not quite sure what you are trying to tell me, but there is definitely a solution to my question "get file locking handle". This is shown on the one hand by Remy's answer and on the other hand by the fact that the handle I am looking for can be determined with Handle.exe. – Jachuc Dec 17 '21 at 12:13
  • no correct solution in generic case. if opened file handle exist - it easy find and close. but here alwas raice exist and process will be not stable after this – RbMm Dec 17 '21 at 12:28

0 Answers0