Определите, используется ли файл в Perl в Windows - PullRequest
5 голосов
/ 10 июля 2010

Я пишу какой-то Perl, который принимает ТВ-шоу, записанные в Windows Media Center, и перемещает / переименовывает / удаляет их в зависимости от определенных критериев.

Поскольку Perl запускается довольно часто, я бы хотел точно определить,используется ли файл (или, другими словами, шоу находится в процессе записи), поэтому я могу избежать каких-либо действий с ним.

Мой текущий метод проверяет состояние файла (используя"stat") и сравнивает его снова через 5 секунд, например так:

sub file_in_use
{
  my $file = shift;

  my @before = stat($file);
  sleep 5;
  my @after = stat($file);

  return 0 if ($before ~~ $after);
  return 1;
 }

Кажется, это работает, но я уверен, что, вероятно, есть лучший и более чистый способ сделать это.

Не могли бы вы посоветовать?

Ответы [ 3 ]

8 голосов
/ 11 июля 2010

Если процесс записи блокирует файл, вы можете попытаться открыть его в режиме чтения-записи и посмотреть, не сработает ли он с ERROR_SHARING_VIOLATION как GetLastError (доступ к которому осуществляется через специальную переменную Perl $^E).

Например:

#! /usr/bin/perl

use warnings;
use strict;

sub usage { "Usage: $0 file ..\n" }

die usage unless @ARGV;

foreach my $path (@ARGV) {
  print "$path: ";

  if (open my $fh, "+<", $path) {
    print "available\n";
    close $fh;
  }
  else {
    print $^E == 0x20 ? "in use by another process\n" : "$!\n";
  }
}

Пример вывода при Dir100526Lt.pdf, открытом программой чтения Adobe:

C:\Users\Greg\Downloads>check-lock.pl Dir100526Lt.pdf setup.exe
Dir100526Lt.pdf: in use by another process
setup.exe: available

Помните, что каждый раз, когда вы сначала проверяете условие, а затем действуете на основев результате этого теста вы создаете условие гонки .Кажется, что худшее, что может укусить вас в вашем приложении, заключается в следующей неудачной последовательности:

  1. проверить видео на доступность, как указано выше
  2. ответ: доступно!
  3. тем временем запускается рекордер и блокируется видео
  4. обратно в вашу программу, вы пытаетесь переместить видео, но оно не удается с нарушением обмена
1 голос
/ 10 июля 2010

Единственное улучшение, которое я бы предложил, это stat все ваши файлы одновременно, так что вам нужно всего лишь спать 5 секунд один раз вместо сна 5 секунд для каждого файла:

my (%before, %after);
foreach my $file (@files_that_might_be_in_use) {
    $before{$file} = [ stat $file ];
}
sleep 5;
foreach my $file (@files_that_might_be_in_use) {
    $after{$file} = [ stat $file ];

    if ( $before{$file} ~~ $after{$file} ) {
        # file is not in use ... 
    } else {
        # file is in use ... 
    }
}
0 голосов
/ 04 мая 2018

Существует API Windows, в котором будет указано количество процессов, которые сохраняют файл открытым.Это Менеджер перезапуска (Rststmgr.dll).На основании художественного Как узнать, какой процесс имеет открытый файл? , и с помощью Win32 :: API вы можете преобразовать программу в Perl-программу, которая сообщает вам количество процессов, имеющих файлоткрыть и даже перечислить идентификаторы процесса.

Каждый тест должен быть последовательностью RmStartSession, RmRegisterResources, RmGetList, RmEndSessionИспользуйте encode("UTF-16LE",$filename) для создания строки типа CWSTR.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...