I'm writing some Perl which takes TV shows recorded on Windows Media Center and moves/renames/deletes them depending on certain criteria.
Since the Perl runs fairly frequently, I'd like to cleanly determine whether or not the file is in use (in other words, the show is in the process of being recorded) so I can avoid doing anything with it.
My current method looks at the status of a file (using "stat") and compares it again after 5 seconds, like so:
sub file_in_use
{
my $file = shift;
my @before = stat($file);
sleep 5;
my @after = stat($file);
return 0 if ($before ~~ $after);
return 1;
}
It seems to work, but I'm concious that there is probably a better and cleaner way to do this.
Can you please advise?
A windows API exists that will list the number of processes that keep a file open. It is the Restart Manager (Rststmgr.dll). Based on artical How do I find out which process has a file open?, and with help of Win32::API you can transform the program in a Perl program that tells you the number of processes that have a file open and even list the process ids.
Each test should be a sequence of RmStartSession, RmRegisterResources, RmGetList, RmEndSession. Use
encode("UTF-16LE",$filename)
to make aCWSTR
type string.If the recording process locks the file, you could attempt to open it in read-write mode and see if it fails with
ERROR_SHARING_VIOLATION
asGetLastError
(accessed via Perl's$^E
special variable).For example:
Sample output with
Dir100526Lt.pdf
open by the Adobe reader:Be aware that any time you first test a condition and then later act based on the result of that test, you're creating a race condition. It seems that the worst this could bite you in your application is in the following unlucky sequence:
The only improvement I would suggest is to
stat
all of your files at once, so you only need to sleep for 5 seconds one time instead of sleeping 5 seconds for every file: