Подтвердить что ты не робот

Msbuild "Не удалось удалить каталог"

Один из наших проектов CruiseControl.NET постоянно прерывается, потому что сбой задачи msbuild с

ошибка MSB3231: невозможно удалить каталог "d:\Somewhere\Dir\Admin". Неверный параметр.

Соответствующая строка msbuild script - это просто

<RemoveDir Directories="$(DistributionDir)\Admin" Condition="Exists('$(DistributionDir)\Admin')" />

Когда я смотрю на состояние после неудачной сборки, содержимое каталога было успешно удалено, но сам пустой каталог. И следующая сборка обычно преуспевает (нужно удалить только пустой каталог). Обратите внимание, что проблема, похоже, не в том, что "какой-то другой процесс (например, антивирус) блокирует каталог", ошибка не "запрещена", но очень странный "параметр неверен".

Я отслеживал сборку с помощью SysInternals Process Monitor, и результат странный - все идет так, как ожидалось, содержимое каталога перечисляется, удаляется, а когда перечисление каталога верхнего уровня заканчивается "НЕТ БОЛЬШЕ ФАЙЛОВ", каталог закрыт, и... ничего. Никакая другая операция не попадает на монитор процесса:

10:04:09,9190557    MSBuild.exe 3516    QueryDirectory  D:\Somewhere\Dir\Admin  NO MORE FILES   
10:04:09,9190928    MSBuild.exe 3516    CloseFile       D:\Somewhere\Dir\Admin  SUCCESS 

Следующая (успешная) попытка сборки - это просто удачное удаленное удаление каталога:

10:31:21,8616463    MSBuild.exe 1760    CreateFile  D:\Somewhere\Dir\Admin  SUCCESS Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:31:21,8616861    MSBuild.exe 1760    QueryDirectory  D:\Somewhere\Dir\Admin\*    SUCCESS Filter: *, 1: .
10:31:21,8617305    MSBuild.exe 1760    QueryDirectory  D:\Somewhere\Dir\Admin  SUCCESS 0: ..
10:31:21,8617589    MSBuild.exe 1760    QueryDirectory  D:\Somewhere\Dir\Admin  NO MORE FILES   
10:31:21,8618209    MSBuild.exe 1760    CloseFile   D:\Somewhere\Dir\Admin  SUCCESS 
10:31:21,8621579    MSBuild.exe 1760    CreateFile  D:\Somewhere\Dir\Admin  SUCCESS Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:31:21,8622118    MSBuild.exe 1760    QueryAttributeTagFile   D:\Somewhere\Dir\Admin  SUCCESS Attributes: D, ReparseTag: 0x0
10:31:21,8622408    MSBuild.exe 1760    SetDispositionInformationFile   D:\Somewhere\Dir\Admin  SUCCESS Delete: True
10:31:21,8622676    MSBuild.exe 1760    CloseFile   D:\Somewhere\Dir\Admin  SUCCESS 

По какой-то причине MSBuild/Windows обнаруживает какую-то недопустимую ошибку параметра перед удалением каталога, но я понятия не имею, где искать. (Я также пытался запустить chkdsk, ничего не найдено. Я также удалил и воссоздал родительский каталог D:\Somewhere\Dir, ничего не изменилось.)

Итак - любая идея, в которой может быть проблема, и как я должен исследовать дальше?

(Я не уверен, где этот вопрос должен был пройти, это где-то между SO, Progs SE, Server Fault, Superuser...)

4b9b3361

Ответ 1

Я не могу сказать, почему он терпит неудачу, но если папка остается единственной, можно ли построить сборку правильно? Если это так, обходным путем было бы указать ContinueOnError = "True".

Ответ 2

Пробовал много вещей, но я не мог понять, почему это иногда терпит неудачу, когда каталог не пуст; в нашем случае каталог содержит символические ссылки, если это имеет значение. В любом случае мне не нравится использовать ContinueOnError, так как это означает, что когда есть реальная ошибка, вы этого не знаете или вам нужно выполнить дополнительную проверку, например <Error Condition="Exists... после каждого RemoveDir. Решение, которое мы используем сейчас, - это явно освободить каталог, после чего у msbuild нет никаких проблем с его удалением:

<MSBuild.ExtensionPack.FileSystem.Folder Condition="Exists( $(PathtoEmpty) )"
   TaskAction="RemoveContent" Path="$(PathtoEmpty)" />
<RemoveDir Directories="$(PathtoEmpty)" />

Ответ 3

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

Ответ 4

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

<RemoveDir Directories="$(DistributionDir)\Admin" />

Ответ 5

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

Я могу использовать удаление содержимого вместо удаления каталога, как показано ниже.

 <MSBuild.ExtensionPack.FileSystem.Folder Condition="Exists( $(OutputPath) )"   TaskAction="RemoveContent" Path="$(OutputPath)" />