title: PowerShell - Close File Before using Remove-Item
body: <p>I am working on a script to inspect the contents of 2 .zip files, compare the names of a file in each .zip (as a datetime) and then remove the oldest of the 2 files. Everything seems to be working fine until it comes to the very end when I am trying to delete the oldest file with a simple 'Remove-Item' (I have tried the -Force option with no improvement). Every attempt I make results in this error:</p>
  
  <blockquote>
    <p>Remove-Item : Cannot remove item C:\Scripts\Test2.zip: The process
    cannot access the file 'C:\Scripts\Test2.zip' because it is being used
    by another process. At line:44 char:5
    +     Remove-Item $newLocation -Force
    +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : WriteError: (C:\Scripts\Test2.zip:FileInfo) [Remove-Item], IOException
        + FullyQualifiedErrorId : RemoveFileSystemItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand</p>
  </blockquote>
  
  <p>This is the script I have come up with (be gentle, it's probably not the smoothest thing on earth):</p>
  
  <pre><code>$scriptLocation = "C:\Scripts\"
  $oldLocation = "C:\Scripts\Test1.zip"
  $newLocation = "C:\Scripts\Test2.zip"
  
  cd $scriptLocation
  
  $fileOld = .\GetZipContents.ps1 -FileName $oldLocation | Where {$_.FileExtn -eq ".txt"}
  $fileNew = .\GetZipContents.ps1 -FileName $newLocation | Where {$_.FileExtn -eq ".txt"}
  
  function Convert-DateString ([String]$Date, [String[]]$Format)
  {
     $result = New-Object DateTime
  
     $convertible = [DateTime]::TryParseExact(
        $Date,
        $Format,
        [System.Globalization.CultureInfo]::InvariantCulture,
        [System.Globalization.DateTimeStyles]::None,
        [ref]$result)
  
     if ($convertible) { $result }
  }
  
  $oldName = $fileOld.FileName
  $oldDate = $oldName.Substring(0,$oldName.Length-4)
  
  $newName = $fileNew.FileName
  $newDate = $newName.Substring(0,$newName.Length-4)
  
  
  $convOldDate = Convert-DateString -Date $oldDate -Format 'MMMM_dd_yyyy'
  $convNewDate = Convert-DateString -Date $newDate -Format 'MMMM_dd_yyyy'
  $compare = $convOldDate -ge $convNewDate
  
  If($compare -eq $True)
  #OLD
  {
      Remove-Item $oldLocation -Force
      "OLD FILE IS OLD - REMOVING: ({0})" -f ($oldLocation) 
  }
  Else
  #NEW
  {
      Remove-Item $newLocation -Force
      "NEW FILE IS NEW - REMOVING: ({0})" -f ($newLocation)
  } 
  </code></pre>
  
  <p>And this is the GetZipContents.ps1 being called in $fileOld and $fileNew:</p>
  
  <pre><code>[cmdletbinding()]            
  param(            
   [Parameter(Mandatory=$true)]            
   [string[]]$FileName,            
   [String]$ExportCSVFileName            
  )            
  #Exit if the shell is using lower version of dotnet            
  
  $dotnetversion = [Environment]::Version            
  if(!($dotnetversion.Major -ge 4 -and $dotnetversion.Build -ge 30319)) {            
   write-error "You do not have Microsoft .Net Framework 4.5 installed. Script exiting..."            
   exit(1)            
  }            
  
  # Import dotnet libraries            
  
  [Void][Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')            
  $ObjArray = @()            
  foreach($zipfile in $FileName) {            
  if(Test-Path $ZipFile) {            
   $RawFiles = [IO.Compression.ZipFile]::OpenRead($zipFile).Entries            
   foreach($RawFile in $RawFiles) {            
  
    $object = New-Object -TypeName PSObject            
    $Object | Add-Member -MemberType NoteProperty -Name FileName -Value $RawFile.Name            
    $Object | Add-Member -MemberType NoteProperty -Name FullPath -Value $RawFile.FullName            
    $Object | Add-Member -MemberType NoteProperty -Name CompressedLengthInKB -Value ($RawFile.CompressedLength/1KB).Tostring("00")            
    $Object | Add-Member -MemberType NoteProperty -Name UnCompressedLengthInKB -Value ($RawFile.Length/1KB).Tostring("00")            
    $Object | Add-Member -MemberType NoteProperty -Name FileExtn -Value ([System.IO.Path]::GetExtension($RawFile.FullName))            
    $Object | Add-Member -MemberType NoteProperty -Name ZipFileName -Value $zipfile            
    $ObjArray += $Object            
    if(!$ExportCSVFileName) {            
     $Object            
    }            
   }            
  } else {            
   Write-Warning "$ZipFileInput File path not found"            
  }            
  if ($ExportCSVFileName){            
   try {            
    $ObjArray  | Export-CSV -Path $ExportCSVFileName -NotypeInformation            
   } catch {            
    Write-Error "Failed to export the output to CSV. Details : $_"            
   }            
  }            
  
  }
  </code></pre>
  
  <p>Which I got from here: <a href="http://techibee.com/powershell/reading-zip-file-contents-without-extraction-using-powershell/2152" rel="nofollow">http://techibee.com/powershell/reading-zip-file-contents-without-extraction-using-powershell/2152</a></p>
  
  <p>I have run Handle.exe to find the process holding these files open, and it shows that the PowerShell ISE itself it the problem. </p>
  
  <p>Any help would be appreciated. I tried to search for similar problems, but only found issues where other processes held open the file, which you can then kill with Handle.exe. I am not sure how to do this if PowerShell ISE needs to let go...</p>