9

We have a large number of builds happening often with a large amount of source. Therefore, we want the builds sources and staging directories clearing after each build. I am using vNext builds in TFS 2015 Update 1 on-prem. I have created a PowerShell script as the final task which executes the delete:

[CmdletBinding()]
param()

begin {
    function Delete-Directory {
        param([string]$directory)

        Write-Output "Attempting to delete '$($directory)'"

        if (Test-Path $directory -pathType container) {
            Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Recurse -Force
            Write-Output "Successfully deleted the directory: '$($directory)'"
        } else {
            Write-Output "Failed to delete '$($directory)' as it does not exist"
        }
    }
}

process {
    Delete-Directory $env:BUILD_SOURCESDIRECTORY
    Delete-Directory $env:BUILD_STAGINGDIRECTORY
}
end{}

Originally, instead of using Get-ChildItem .... | Remove-Item, I was using Remove-Item *path* -Recurse -Force but apparently there is a problem with the recurse parameter of Remove-Item. Originally it was sometimes working. Now it is never working.

I have tried many different variants and here are some of the results:

With -Recurse and -Force

Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Recurse -Force

equals:

Get-ChildItem : Access to the path 'E:\GeneralAgent1\_work\3\s\TfsBuild' is
denied.
At E:\GeneralAgent1\_work\3\s\TfsBuild\Scripts\DeleteSources.ps1:11 char:5
+ Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Recurse -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : PermissionDenied: (E:\GeneralAgent1\_work\3\s\TfsBuild:String) [Get-ChildItem], Unauthor
izedAccessException
    + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

No -Recurse

Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Force

equals:

Remove-Item : Windows PowerShell is in NonInteractive mode. Read and Prompt
functionality is not available.
At E:\GeneralAgent1\_work\3\s\TfsBuild\Scripts\DeleteSources.ps1:11 char:54
+ Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Force
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand

No -Force

Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Recurse

Returns lots of errors, 1 that permission denied and others that cannot delete due to not being emtpy due to permission denied prior:

Remove-Item : Cannot remove item
E:\GeneralAgent1\_work\3\s\Proxies\Development\Isd.Proxies.BO_16.01.1\Avalara\StyleCop.Cache:
You do not have sufficient access rights to perform this operation.
At E:\GeneralAgent1\_work\3\s\TfsBuild\Scripts\DeleteSources.ps1:11 char:54
+ Get-ChildItem -Path $directory -Force -Recurse | Remove-Item -Recurse
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : PermissionDenied: (StyleCop.Cache:FileInfo) [Remove-Item], IOException
    + FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
......
Lots

No -Recurse or -Force

Get-ChildItem -Path $directory -Force -Recurse | Remove-Item

equals:

Remove-Item : Windows PowerShell is in NonInteractive mode. Read and Prompt
functionality is not available.
At E:\GeneralAgent1\_work\3\s\TfsBuild\Scripts\DeleteSources.ps1:11 char:54
+ Get-ChildItem -Path $directory -Force -Recurse | Remove-Item
+ ~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Remove-Item], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RemoveItemCommand

I have also tried other combinations and played with the parameters of Get-ChildItem and get similar results.

The build agents account has full permission to the root directory.

Any help please?

Nidhish Krishnan
  • 20,593
  • 6
  • 63
  • 76
Rodders
  • 2,425
  • 2
  • 20
  • 34

2 Answers2

17

You should be able to delete everything if you go from the bottom up. Sort the results of Get-ChildItem by their full name in descending order before deleting the items:

Get-ChildItem -Path $directory -Force -Recurse |
  Sort-Object -Property FullName -Descending |
  Remove-Item -Recurse -Force
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • This appears to have done the trick. and it makes sense too. I guess that not sorting would just enumerate in some standard order and try to delete the parent before the child. Thanks – Rodders Jan 06 '16 at 15:50
0

Not sure this is your fix but I do it just a bit differently

Get-ChildItem $FolderPath | ForEach-Object ($_){
    Remove-Item $_.FullName -Recurse -Force
}
Sean Rhone
  • 250
  • 2
  • 7
  • Remove-Item : Cannot remove item E:\GeneralAgent1\_work\3\s\Proxies\Development: The directory is not empty. – Rodders Jan 06 '16 at 14:54
  • Sounds like you have something holding onto a file. Have you tried not executing this script as part of the build and execute it manually after the build completes? It might help trouble shoot if the script is the issue of if the timing of the script execution is the issue. – Sean Rhone Jan 06 '16 at 15:21
  • Then you have a execution timing issue. TFS is not done with that folder and you're trying to delete it. – Sean Rhone Jan 06 '16 at 15:46
  • I could perhaps fire off some event which waits for completion before attempting to delete however, Ansgars suggestion is a good workaround. Thanks – Rodders Jan 06 '16 at 15:51