Tracking when an application is "done" with a file

delphi package - easy access to kernel objects etc.
Post Reply
Leander van Eck
Posts: 19
Joined: Fri Dec 23, 2005 1:40 pm
Location: Eindhoven, The Netherlands
Contact:

Tracking when an application is "done" with a file

Post by Leander van Eck »

Hi Madshi,

I have the following problem:

I need to be able to see when a user has closed a file in another application (e.g. Ms Word). (we use this to store the file in a database).

I'm trying this using madKernel by checking wether a handle remains valid. However when the file is saved in Ms Word (ctrl+s) the handle is no longer valid. To avoid this problem i'm looping through all handles inside the process once more to see if a new handle has been created for the file.

I'm doing this with the following code.
THandleTracker is a thread with 2 private variables:
FProcess - pointer to the IProcess interface
FFileLoc - string to the location of the file that is being checked

Code: Select all

procedure THandleTracker.Execute;
var
  lvHandle : IHandle;

  function ValidProcess : Boolean;
  begin
    Result := Assigned(FProcess) and FProcess.IsStillValid;
  end;

  function ValidHandle : Boolean;
  begin
    Result := Assigned(lvHandle) and lvHandle.isstillvalid;
  end;

  function NewValidHandle : Boolean;
  begin
   //GetFileHandleFromProcess retrieves a new handle inside the FProcess (interface IProcess) using the filelocation. 
   lvHandle := GetFileHandleFromProcess(FProcess, FFileLoc);
    Result := ValidHandle;
  end;

begin
  lvHandle := nil;
  while (not Terminated) and ValidProcess and (ValidHandle or NewValidHandle)
   do lvHandle.WaitFor( 100 );

    if not Terminated
    then Synchronize( DoHandleDestroyed );
end;
A few questions:
- Is there a better way to check when a file handle is released (and no new handle to the file is created by the process)?
- Can i retrieve the file handle by any other means besides looping through all handles inside the process?
- Is it possible the new handle is not created "immediately". i.o.w could it be that my DoHandleDestroyed method is called when MS Word is still creating a new handle to the file?

I hope i explained my situation well, i've literally invested hours into this project and must now decide wether its worth investing more time or take another route (though this is my best idea so far :))[/code]
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

I'm not sure exactly what you're trying to do. I think while the user is working in Word, there may be a handle open to that file or not. That depends on the program being used. Many programs probably won't have a handle open to the file all the time. They'll probably only open a handle to the file when they want to save it. And once they've saved it, the handle is likely to be closed again.

If you want to target Word specifically, you may want to use the Word COM stuff, which may give you much more details over what is happening. If you want your program to work with any application out there and not just with Word, things are getting more difficult.

Basically I guess you want to be notified whenever a file was saved/changed? How about using the shell notification stuff?
Leander van Eck
Posts: 19
Joined: Fri Dec 23, 2005 1:40 pm
Location: Eindhoven, The Netherlands
Contact:

Post by Leander van Eck »

Well, to be more specific, i'm working on a document/file management system for multiple users. A user can edit a file after he/she has checked-out the file first (to prevent multiple users from working in the same file). When the file is checked out the appropiate program wil open the file.

To make things easier for the user i want to send a check-in request after the user closes the file. So they don't forget to check in the file.

I realise not all applications will hold a handle open, but i'm not aiming for perfection (yet :)). Users will be asked to check-in those files during the OnClose Query for my application.

I could send the check-in request after a shell notification, but this means that the request might appear while the user is still working in the file. So now i use a combination of both shell notifications (madShell) and tracking file handles until they are released (madKernel).

This probably is not the most likely use for madKernel, but as before madCollection has been my best guess and so far it is still my only one.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Another approach would be to hook the "NtClose" API (by using madCodeHook), which is internally called by CloseHandle. You would need to hook NtClose in the context of the target process. In order to do that you'd have to write a little hook dll which in its initialization hook that API. You'd then be "notified" whenever the target application closes a handle. You wouldn't need to poll, anymore. Don't know if it's worth the effort, though.
Leander van Eck
Posts: 19
Joined: Fri Dec 23, 2005 1:40 pm
Location: Eindhoven, The Netherlands
Contact:

Post by Leander van Eck »

That sounds really cool, though i must admit that i not know much about api hooking yet.

Would it be possible to system wide hook the ntClose and track the handle back to the location of the file? I have managed to get the correct filename from an IHandle interface so obtaining the IHandle interface would suffice.
Could i also hook something like OpenHandle?

Perhaps i could check wether a file is closed without being opened again within a certain time frame. (In case some application saves the file and recreates a new handle).

This would really be worth the effort since i now check all processes to see if any of them have a handle to a specific file, which is cpu consuming.

Many thanks for the help so far, it is really appreciated.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Sorry for the late reply...
Leander van Eck wrote:Would it be possible to system wide hook the ntClose and track the handle back to the location of the file? I have managed to get the correct filename from an IHandle interface so obtaining the IHandle interface would suffice.
That would be possible. However, asking the file name when you only have a handle does cost some performance. So you may slow the OS down too much doing this.
Leander van Eck wrote:Could i also hook something like OpenHandle?
Sure. For files that would be NtCreateFile/NtOpenFile, if you want to hook the lowest level in user land. Or you could hook all the usual win32 APIs like CreateFile etc. But they all end up in NtCreateFile/NtOpenFile in the NT family.
Post Reply