Как определить, что файл используется перед удалением? - PullRequest
4 голосов
/ 03 октября 2009

Я пишу службу Windows, которая может удалить файл в какой-то момент. Поскольку служба работает с обычным файловым вводом-выводом, возможно, файл может использоваться во время удаления.

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

try
{
    File.Delete(file);
    Status = ResponseStatus.Ok;
}
catch (IOException e)
{
    Status = ResponseStatus.FileInUse;
}
finally
{
    return Status;
}

Как я могу определить, используется ли файл без исключения?

Ответы [ 4 ]

13 голосов
/ 03 октября 2009

Нет смысла пытаться сразу определить, используется ли файл - что если кто-то откроет файл между вашим кодом обнаружения и вашим кодом удаления? Вам все еще понадобится ваш существующий код, чтобы справиться с этим делом.

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

3 голосов
/ 03 октября 2009

Расширение на правильный ответ Ричи

При работе с файловой системой вы никогда не сможете надёжно выполнить операцию. Все, что вы можете сделать, это попробовать операцию и проверить, удалось ли она.

Файловая система - движущаяся цель, которую вы не можете контролировать. Любое количество внешних и других пользовательских событий может влиять на файловую систему вне вашего контроля. Во многих отношениях это похоже на многопоточное программирование, где синхронизация невозможна. Всякий раз, когда вы видите код, подобный следующему, появляется небольшая ошибка

if (File.SomeTypeOfCheck(somePath) {
  File.DoSomeOperation(somePath);
}
3 голосов
/ 03 октября 2009

Как говорит Ричи, ловить исключение, вероятно, лучший подход здесь.

Но что, если вы хотите удалить 10 файлов и не хотите, чтобы они потерпели неудачу на полпути? Вам действительно нужен какой-то способ защиты всей транзакции. Так что полезно , чтобы иметь возможность пассивно проверять, используется ли файл. Вы можете определить, используется ли файл (или только для чтения, что также делает его недоступным для восстановления), просто попытавшись открыть его для записи (а затем, если вам это удастся, немедленно закрыть его). Это само по себе не гарантирует, что последующая попытка удаления будет успешной.

Другие подходы, которые могли бы работать: - переместить / переименовать файл (ы) перед удалением (поместить их в безопасное место, чтобы вы знали, что они не могут быть впоследствии открыты другим процессом), чтобы вы могли «отменить» транзакцию, если какая-либо из отдельных операций перемещения не удалась - поймать исключение и поставить в очередь будущую попытку удалить файл (либо в вашей собственной программе, либо вы можете пометить файл для автоматического удаления Windows при следующей перезагрузке)

3 голосов
/ 03 октября 2009

Если вы просто хотите проверить, было ли удаление успешным, не обнаружив исключения, вам просто нужно объявить P / Invoke для функции DeleteFile.

[DLLImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeleteFile(string fileName);

Это вернет true, если удаление было успешным, и false, если это не было. Если вам нужен конкретный код ошибки, вы можете позвонить Marshal.GetLastWin32Error()

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