RaelB 4 Posted January 10, 2021 Hi, When trying to modify or overwrite an existing file, I get this error: Quote EFCreateError with message 'Cannot create file "C:\Users\User\AppData\Local\Temp\....". The process cannot access the file because it is being used by another process'. Similarly the file cannot be deleted with SysUtils.DeleteFile. It seems that the file is actually in use within the same application (since if I close the app and restart it the file can be deleted...) Is there any way i.e. via code or perhaps an external tool, I can find out which piece of code is locking/holding the file? Similar to how when there is a memory leak, FastMM can give a report of which code block created the object. Thanks Share this post Link to post
FPiette 383 Posted January 10, 2021 50 minutes ago, RaelB said: Is there any way i.e. via code or perhaps an external tool, I can find out which piece of code is locking/holding the file? Using SysInternals ProcessExplorer, you'll see all applications and services running. When selecting one, you can display the handles that are active, among which the files. Using SysInternals ProcessMonitor, you can see in real time all the operation one or more application are doing with file/registry/process/network. You can set a filter to the file you are interested in to limit the size of display. Both tools are free. SysInternals is actually Microsoft... Share this post Link to post
David Heffernan 2345 Posted January 10, 2021 48 minutes ago, FPiette said: Using SysInternals ProcessExplorer, you'll see all applications and services running. When selecting one, you can display the handles that are active, among which the files. Using SysInternals ProcessMonitor, you can see in real time all the operation one or more application are doing with file/registry/process/network. You can set a filter to the file you are interested in to limit the size of display. Both tools are free. SysInternals is actually Microsoft... Question is actually about identifying which piece of code is responsible for the lock. Asker already knows which process has it. Share this post Link to post
Anders Melander 1782 Posted January 10, 2021 Set a break point on the CreateFile (and maybe OpenFile) API function and set the break condition to match the name of the file somehow. Share this post Link to post
Guest Posted January 10, 2021 8 hours ago, RaelB said: Is there any way i.e. via code or perhaps an external tool, I can find out which piece of code is locking/holding the file? Similar to how when there is a memory leak, FastMM can give a report of which code block created the object. Use DDetours https://github.com/MahdiSafsafi/DDetours Look at the demo which is hooking MessageBox API, study it then hook the following API's and you will have the culprit CreateFile CreateFileEx The thing is you need CloseHandle to pair up each create with close, but CloseHandle might be tricky as it is used with many handle types, so by only tracking CreateFile, you can find the last one succeeded in opening/creating the file and didn't close its handle yet. Share this post Link to post
FPiette 383 Posted January 11, 2021 14 hours ago, Kas Ob. said: study it then hook the following API's and you will have the culprit CreateFile CreateFileEx Add the following API: LockFile, LockFileEx. Share this post Link to post
Remy Lebeau 1394 Posted January 11, 2021 (edited) On 1/10/2021 at 3:51 AM, David Heffernan said: Question is actually about identifying which piece of code is responsible for the lock. Asker already knows which process has it. True. However, when using Process Monitor, the user can see WHEN the file is being opened by his app in real-time. Maybe he can match that up to a specific operation the app is performing at that time, and then he can track down the code behind that operation to see if it is leaking the file handle. Edited January 11, 2021 by Remy Lebeau 2 Share this post Link to post
Guest Posted January 11, 2021 There is many ways to find it but the best and fastest way in this case is to use Handle from sysinternals https://docs.microsoft.com/en-us/sysinternals/downloads/handle it is command line so run it like this Quote handle64.exe > 1.txt then open that 1.txt file and search for your file. Share this post Link to post
Remy Lebeau 1394 Posted January 11, 2021 1 hour ago, Kas Ob. said: There is many ways to find it but the best and fastest way in this case is to ... "Best" is a bit subjective. What you describe could be the EASIEST way, but not necessarily the BEST or FASTEST way. An alternative that doesn't involve spawning a separate process or using any file I/O would be to use NtQuerySytemInformation(SystemHandleInformation) instead to find open handles that belong to your process, and then resolve which files they refer to. See Enumerating opened handles from a process. Yes, it is more work to code for, but it may be much more efficient in the long run. Share this post Link to post
Guest Posted January 11, 2021 55 minutes ago, Remy Lebeau said: "Best" is a bit subjective. Right, i missed the word best tool, and what i want to say it is the best to see opened files and their access mode (read/write..) system wide. Not many know about Handle so i was comparing it to other external tools. Share this post Link to post
Fr0sT.Brutal 900 Posted January 12, 2021 (edited) (side note) Generally, if one doesn't even know when his app opens a file, he has really big problems. First, all places in code that open and close file of interest should be located. Then you can set breakpoints to these places or add some logging. If code wasn't written by WinAPI fanatics, all file operations are performed via SysUtils.File* or old-school System.AssignFile/Reset/Write, so setting breakpoints to these functions will help. Edited January 12, 2021 by Fr0sT.Brutal Share this post Link to post
RaelB 4 Posted January 12, 2021 Thanks all for the suggestions. The DDetours library was really helpful in this situation (in combination with logging), and helped me locate the problem fairly easily. On 1/10/2021 at 8:43 PM, Kas Ob. said: The thing is you need CloseHandle to pair up each create with close, but CloseHandle might be tricky as it is used with many handle types, so by only tracking CreateFile, you can find the last one succeeded in opening/creating the file and didn't close its handle yet. Yeah not that tricky. I just used a TStringList to keep track of opened files (i.e. Handles) and only logged calls to CloseHandle that had an entry in the stringlist (and then removed them..) Share this post Link to post