Определить, можно ли переместить каталог в NTFS

У меня есть каталог, содержащий множество файлов в сложном дереве подкаталогов.

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

Если да, то как я могу программно определить, можно ли переместить каталог A в B?

Есть ли какой-либо API, связанный с блокировкой, который может помочь мне в этом?

Я использую С# на разделах NTFS.


person Assaf Lavie    schedule 18.07.2010    source источник
comment
Если файлы используются или есть другие ошибки, каталог вообще не может быть перемещен, это не связано с производительностью ;-). Разве вы на самом деле не спрашиваете, как определить, возможно ли перемещение в другое место на том же логическом диске?   -  person Abel    schedule 18.07.2010
comment
хорошая точка зрения. Думаю, это то, о чем я спрашиваю. Я немного перефразирую.   -  person Assaf Lavie    schedule 18.07.2010


Ответы (2)


Такого рода API-интерфейсы «может ли это работать» не существуют в многозадачных операционных системах. Они по своей сути ненадежны, как проверка того, заблокирован ли файл. Такой тест может вернуть «не заблокировано», тогда ваш поток может быть вытеснен, а другой поток в другом процессе может заблокировать файл. Когда ваш поток вернет ЦП, вы обнаружите, что файл заблокирован, хотя тест сказал, что это не так.

Единственный способ сделать это — фактически выполнить операцию, а затем найти ошибку, указывающую на то, что это невозможно. Исключение в C#, используйте оператор try, чтобы перехватить IOException. С этим не так просто иметь дело, но, по крайней мере, NTFS позволяет переименовывать или перемещать заблокированный файл.

person Hans Passant    schedule 18.07.2010
comment
Это сработает только в том случае, если операция перемещения гарантированно будет атомарной. Я не вижу ничего в документах API, которые предполагали бы, что функция всегда вызывает немедленное срабатывание, если она не может переместить каталог путем переименования... - person Assaf Lavie; 18.07.2010
comment
Возможно, вам придется P/Invoke MoveFileTransacted(), доступный в Vista и выше. Но в противном случае нет, частичный отказ — это то, с чем вам придется иметь дело. - person Hans Passant; 18.07.2010
comment
Такая же функциональность есть и в Windows XP. Я просто сомневаюсь, что нет никакого способа задействовать его программно. Windows XP реализует перемещение путем переименования, когда это возможно, и возвращается к рекурсивному перемещению в случае сбоя. Мне нужно иметь возможность сделать то же самое на XP самостоятельно. - person Assaf Lavie; 19.07.2010
comment
Базовая API-функция MoveFile() либо завершится успешно, либо завершится ошибкой, частичных сбоев не бывает. Я не знаю об эквивалентах .NET, но вы можете использовать P/Invoke. - person Harry Johnston; 22.03.2015

Есть так много вещей, которые могут привести к сбою операции перемещения:

  • Файл в каталоге заблокирован
  • У вас нет разрешения на запись на B
  • У вас нет разрешения на запись в A (копирование работает, но не перемещается)
  • У вас есть разрешение на запись на A, но не на каждый файл внутри
  • повреждение данных (сломанный жесткий диск)
  • Кто-то уже переместил эту папку

И, возможно, многое другое, о чем вы не будете думать, пока это не будет запущено в производство.

В любом случае, NTFS поддерживает транзакции начиная с Vista/2008, так что вы могли бы обернуть свою задачу в TransactionScope:

Вот статья об этом: http://msdn.microsoft.com/en-us/magazine/cc163388.aspx

И отличный учебник здесь: community.bartdesmet.net

person Jürgen Steinblock    schedule 18.07.2010
comment
также в редких случаях у вас может не хватить свободного места для размещения нового большего буфера $index. - person Dominik Weber; 25.08.2010
comment
Открытое командное окно, активное в каталоге или одном из его подкаталогов, также приведет к сбою любой операции перемещения или удаления. - person springy76; 22.09.2011