9
votes

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?

2

2 Answers

17
votes

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
0
votes

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

Get-ChildItem $FolderPath | ForEach-Object ($_){
    Remove-Item $_.FullName -Recurse -Force
}