I have a Delphi app that regularly writes to a local disk file. Occasionally it is unable to access the file - a sharing violation results when it tries to open it. A retry after a short delay is all that is needed, but when it occurs, I would like to report the process that prevented the access.
Is it feasible when a sharing violation occurs for my program to enumerate all the file handles in use, inspect the filename, and if it matches the name of my data file, retrieves the process name associated with that handle?
Some example code would be nice.
You can find a source example for the IFileIsInUse interface by the JEDI project here: https://svn.code.sf.net/p/jedi-apilib/code/jwapi/trunk/Examples/FileIsInUse/Client/FileIsInUseClientExample.dpr
Using NtQuerySystemInformation you can list all opened handles by all the processes then you can use this function to get the file name
If this is your file than raise up a message ...
You have basically two ways
The Easy Way
if you are using Windows Vista or newer try the
IFileIsInUse
interfaceThe Hard Way
if you need a method compatible with Windows XP,Vista,7 and so on. then you use the NtQuerySystemInformation, NtQueryInformationFile and NtQueryObject functions.
These are the steps to proceed
PROCESS_DUP_HANDLE
real
handle to the file.Note 1 : the tricky part of this method is resolve the filename based in a handle. the function
NtQueryInformationFile
hangs in some scenarios (system handles and others) a workaround to prevent the entire application from hanging is call the function from a separate thread.Note 2 : exist another functions like GetFileInformationByHandleEx and GetFinalPathNameByHandle to resolve the filename of a handle. but both exist since Windows viste an d in such case is better use
IFileIsInUse
.Check this sample application tested in Delphi 2007, XE2 and Windows XP and 7. from here you can take some ideas to resolve your issue.
Note : The function
GetProcessIdUsingFile
Only compares the name of the files (not the path).