function Close-FileHandles { param( [parameter(mandatory=$True, HelpMessage='Full or partial file path')] [string]$FilePath ) Write-Host "Searching for locks on path: $FilePath" gps | Where-Object { $_.Path -match $FilePath.Replace("\", "\\") } |% ` { Write-Host "Closing process $_.Name with path: $_.Path" Stop-Process -Id $_.Id -Force } } function Copy-FilesAndFolders { param( [parameter(mandatory=$True, HelpMessage='Source directory from which to copy')] [string]$SourceDir, [parameter(mandatory=$True, HelpMessage='Destination directory to which to copy')] [string]$DestinationDir, [parameter(mandatory=$True, HelpMessage='Clean destination directory before copying')] [bool]$CleanDestinationDir=$False, [parameter(mandatory=$False, HelpMessage='Timeout')] [int]$Timeout=20 ) # Ensure script fails on any errors $ErrorActionPreference = "Stop" if ($CleanDestinationDir -eq $True) { # First, try to remove the folder without explicitly dropping any locks; leave a reasonable # time for services to stop and threads to end for ($j = 0; $j -le 2; $j ++) { Write-Host "Attempting to delete $DestinationDir, since CleanDestinationDir was specified" for ($i = 1; $i -le $Timeout -and (Test-Path -Path $DestinationDir -ErrorAction SilentlyContinue); $i ++) { Write-Host "Attempting to remove folder $DestinationDir ($i of $Timeout)" Remove-Item -Path $DestinationDir -Recurse -Force -ErrorAction SilentlyContinue Start-Sleep -Milliseconds 1000 } if (Test-Path -Path $DestinationDir -ErrorAction SilentlyContinue) { if ($j -eq 0) { Write-Host "Folder is still locked; dropping locks and retrying" Close-FileHandles -FilePath $DestinationDir } else { throw "Unable to clean $DestinationDir; aborting" } } } } Write-Host "Checking whether $DestinationDir directory exists" if (!(Test-Path $DestinationDir -ErrorAction SilentlyContinue)) { # Create the destination folder Write-Host "$DestinationDir does not exist; creating" New-Item -ItemType directory -Path $DestinationDir } # Copy the folder Write-Host "Copying $SourceDir to $DestinationDir" Get-ChildItem -Path $SourceDir |% ` { try { Write-Host "Copying: $_" Copy-Item $_.fullname "$DestinationDir" -Recurse -Force } catch { Write-Host "Destination file appears to be locked; attempting to drop locks on folder" Close-FileHandles -FilePath $DestinationDir } } }