Мы используем TfsDeployer и сценарий PowerShell для удаления папок с помощью Remove-Item
перед развертыванием новой версии. Иногда скрипт PS дает сбой с ошибкой:
Remove-Item: невозможно удалить элемент Services \ bin: процесс не может получить доступ к файлу Services \ bin ', потому что он используется другим процессом Get-ChildItem -Path $ Destination -Recurse | Remove-Item <<<< -force -recurse + CategoryInfo: WriteError: (C: \ Program File .. \ Services \ bin: DirectoryInfo) [Remove-Item], IOException FullyQualifiedErrorId: RemoveFileSystemItemIOError, Microsoft.PowerShell.Commands.RemoveItemCommand
Я пытался следовать ответ (из: Принудительное удаление файлов и каталогов в PowerShell иногда дает сбой, но не всегда) трубку Get-ChildItem -Recurse
в Remove-Item
.
Get-ChildItem * -Include *.csv -Recurse | Remove-Item
Но ошибка все равно периодически возникает. Мы используем разблокировщик чтобы вручную убить приложение блокировки (обычно это w3wp), но я предпочитаю найти автоматическое решение.
Другой (не идеальный) вариант - подавить ошибки PowerShell
Get-ChildItem -Recurse -Force -ErrorAction SilentlyContinue
Любые предложения приветствуются.
Поздно, но кому-то это может пригодиться.
В сценарии автоматизации я рекурсивно просматриваю процессы, чтобы найти все, которые используют путь к каталогу, который я хочу удалить, и уничтожить их.
Иногда другие приложения могут блокировать файл, поэтому я использовал проводник процессов, чтобы найти дескриптор / dll. Если можно убить приложение, я добавляю его в сценарий.
Затем удалите каталог dir.
get-process | foreach{
$pName = $_
if ( $pName.Path -like ( $INSTALL_PATH + '*') ) {
Stop-Process $pName.id -Force -ErrorAction SilentlyContinue
}
}
Remove-Item -Force -Recurse $INSTALL_PATH
Вы можете проверить ошибки, указанные в Remove-Item
командлет. Использовать ErrorVariable
параметр на Remote-Item
чтобы сохранить свои ошибки в переменной, затем перебрать ее, отображая только те ошибки, которые вам нужны.
Get-ChildItem * -Include *.csv -recurse | ForEach-Object {
$removeErrors = @()
$_ | Remove-Item -ErrorAction SilentlyContinue -ErrorVariable removeErrors
$removeErrors | where-object { $_.Exception.Message -notlike '*it is being used by another process*' }
}
Так как это веб-приложение, которое блокирует файл, почему бы вам не сделать iisreset /stop
перед удалением предмета, а затем iisreset /start
потом?
Как уже упоминалось, вы можете запретить IIS блокировать файлы. это Сообщение блога описывает, как переработать единый пул приложений с помощью PowerShell.