Как я могу проверить, можно ли переименовать каталог в VB.NET?

Моя идея состоит в том, чтобы использовать CreateFile из kernel32 и проверять нарушения обмена. Я считаю, что это сработает, потому что я наблюдал за активностью файловой системы с помощью Process Monitor, выдавая команду переименования из CMD, которая, как я знал, потерпит неудачу, и последним действием был неудачный вызов CreateFile, который привел к нарушению общего доступа.

Это информация Process Monitor о вызове.

Desired Access: Read Attributes, Delete, Synchronize
Disposition: Open 
Options: Synchronous IO Non-Alert, Open Reparse Point 
Attributes: n/a 
ShareMode: Read, Write, Delete 
AllocationSize: n/a

Используя этот код VB, я произвел вызов, который дал ту же информацию в Process Monitor, но не вызвал нарушения совместного доступа.

CreateFile(theDirectoryPath, _
           FILE_READ_ATTRIBUTES Or DELETE Or SYNCHRONIZE, _
           FILE_SHARE_READ Or FILE_SHARE_WRITE Or FILE_SHARE_DELETE, _
           Nothing, _
           OPEN_EXISTING, _
           FILE_ATTRIBUTE_DIRECTORY Or FILE_FLAG_BACKUP_SEMANTICS _
               Or FILE_FLAG_OPEN_REPARSE_POINT, _
           Nothing)

Константы взяты из различных MSDN и pinvoke.net.

Если я рекурсивно вызову приведенный выше код для всех подпапок, это в конечном итоге вызовет нарушение общего доступа, но когда CMD отказался переименовывать, он не рекурсировал.

Да, я знаю, что могу просто попытаться перехватить исключение. Но точка, в которой я хочу узнать, можно ли переименовать каталог, и точка, в которой я хочу переименовать каталог, не совпадают. .

ИЗМЕНИТЬ:

Возможно, в этом вопросе была путаница. Меня не интересуют разрешения; Меня беспокоят блокировки файлов.


person Instance Hunter    schedule 29.06.2009    source источник


Ответы (2)


Да, я знаю, что могу просто попытаться поймать исключение. Но точка, в которой я хочу знать, можно ли переименовать каталог, и точка, в которой я хочу переименовать каталог, не совпадают.

На мой взгляд, это проблема дизайна, которая создает состояние гонки. Если вы сначала проверите, а потом переименуете, вы не будете знать, что время переименования, если ваша предыдущая проверка была действительна.

person JP Alioto    schedule 29.06.2009
comment
Вы будете, если вы знаете единственную причину всех предыдущих сбоев переименования и знаете, что пользователь может предотвратить их, если просто предупредит. - person Instance Hunter; 29.06.2009
comment
Как вы можете запретить ОС блокировать файл, не блокируя его самостоятельно? - person JP Alioto; 29.06.2009
comment
Вы не можете. Но вы можете быть достаточно уверены, что этого не произойдет, если вы знаете, что вызвало каждый случай, когда это происходило в прошлом, и знаете, что предупреждение предотвратит это. - person Instance Hunter; 29.06.2009

Не проверено, но это должно работать:

Dim fp As New FileIOPermission(FileIOPermissionAccess.Write, "C:\myfolderpath")
Try
    fp.Demand()
Catch e As SecurityException
    Console.WriteLine("I can't rename this folder.")
End Try

Это «потребует» разрешения на чтение и запись в папке без фактического переименования чего-либо.

Редактировать: вышеизложенное не делает того, что я думал, см. комментарий Стивена ниже.

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

person richardtallent    schedule 29.06.2009
comment
Насколько я могу судить, это возвращает true (не генерирует исключение) для всех допустимых путей, включая несуществующие, корень C: и каталоги, которые нельзя переименовать. - person Instance Hunter; 29.06.2009
comment
Надеюсь, исправлено... Я думаю, что указанное выше ИЛИ должно приводить к поиску по ИЛИ, а не по И, как я и предполагал. - person richardtallent; 29.06.2009
comment
По-прежнему возвращает true для всех путей, упомянутых ранее. Ради интереса я попробовал его с .AllAccess, и он по-прежнему вел себя так же. - person Instance Hunter; 29.06.2009
comment
Это очень распространенное недоразумение: FileIOPermissionAccess проверяет только безопасность доступа к коду (есть ли у сборки достаточно доверия для доступа к этому пути к файлу), а не безопасность файловой системы (есть ли у текущего пользователя разрешение на доступ к этому файлу или папке. - person Stephen Martin; 29.06.2009
comment
Переименование файла в себя довольно четко задокументировано как вызывающее исключение IOException. Я пытаюсь быть терпеливым, но, пожалуйста, проведите хотя бы НЕКОТОРОЕ исследование, прежде чем предлагать что-то еще. - person Instance Hunter; 29.06.2009
comment
Даниэль, не надо раздражаться. Я не пытался избежать IOException в своем другом предложении, я пытался дать вам способ проверить разрешения на переименование, прежде чем переименовывать файл в что-то другое. Ваш вопрос касается необходимости знать, можно ли переименовать файл перед выполнением действия. Переименовать его в себя — один из способов сделать это. - person richardtallent; 01.07.2009
comment
Спасибо за пояснение, Стивен... это имеет больше смысла. - person richardtallent; 01.07.2009
comment
Переименование его в себя ничего вам не говорит. Он просто выдает исключение IOException. Это то, что я говорил. - person Instance Hunter; 02.07.2009