A common complain on Windows platform is that whenever you try to use a file already being used by another process there is no easy way to find out which process is using that file. The canonical sample is trying to delete a file using Windows Explorer:
It happens that Windows Vista introduced a new COM interface named IFileIsInUse that could be used to allow other processes to figure out which process have the file open. Unfortunately, AFAIK (and based on the MSDN documentation), applications must be aware of this interface and actively do something with it if they want to play nicely with other applications, including the OS.
This morning I was reading some blog posts and someone suggested that Windows 7 had finally fixed this
My first try was to run a C# application that just kept a file open until some key is pressed and try to delete the file; Wow! it worked perfectly!
But now I was left wondering whenever this could have something to do with CLR 4.0 changes (since I was compiling with VS 2010). You know, maybe the FCL team decided to do the IFileIsInUse interface dance internally (when you open a FileStream for instance).
In order to solve this doubt I took 2 actions:
- Targeting CLR 2.0 (by changing VS configuration for the project)
- Write a native C++ application to do the same thing as the C# one (the code bellow).
- Compile the same native program (2) with VS 2010 on Windows XP box (which has no support for IFileIsInUse at all)
- Compile the same native program (2) with VS 2010 on Windows Vista box (which does has support for IFileIsInUse)
#include "stdio.h" int main(int argc, char* argv[]) { const char *fileName = "Test.txt"; FILE* p = fopen(fileName, "w+"); if (p == NULL) { printf("Unable to create file..."); return -1; } printf("[%s] Press any key to close the file ", fileName); getchar(); fclose(p); return 0; }and in the first two cases (i and ii) the result was the same: Windows Explorer was able to detect which application had the file open (with no extra effort from my side :)! Really nice! (Ok, I agree, Windows should have been doing this for ages, but better late than never, don't you agree ? :)
By the other hand, in the last 2 cases (iii and iv) explorer failed to detect the application that had the file open (with exclusive rights).
To me looked like on Windows 7 (and 8 also BTW) Windows Explorer is falling back to NtQuerySystemInformation if it cannot find an IFileIsInUse entry in ROT. So I wrote a simple app (DumpROT.cpp) that searched the ROT for IFileIsInUse implementations and as I suspected when I run the app that keeps the "Test.txt" file open, RotDump fails to find any IFileIsInUse in ROT (it looks like even Libreoffice fails to register opened files in the ROT). Some other programs I've tested (including Visual Studio 2012) didn't registered open files either (see the output bellow):
The -verbose command line option instructs DumpROT to show all entries in the ROT irrespective to what these entries references.
As a last test I decided to run MS sample for this interface and voilá it does register an IFileIsInUse reference in the ROT for the chosen file!
This output was obtained by running DumpROT with the same set of opened files from the previous one (since I omitted the -verbose option the tool gave no feedback). Then I run it again, but this time with -verbose option; you can see in the output that no reference to IFileIsInUse was found in ROT. Next step was to run FileIsInUseSample (the MSDN sample with some changes to accept a file path through the command line) and executed DumpROT again; this time you can see that DumpROT found an entry to "output.txt" (the file passed to the sample app) in the ROT.
Unfortunately I don't have MS Office installed here to check whenever it takes advantage of this feature or not.
Happy coding!
Adriano
No comments:
Post a Comment