title: In Powershell how to bypass a certain Product code/Patch code when deleting old .msi?
body: <p>Hey guys hopefully someone can help me. I have a powershell script that identifies old .msi(s) and deletes them from Windows/Installer folder, but I need to add some code to bypass or (skip) a certain Product ID/Source hash. Basically I need the script to skip this: {1610CB69-BE80-41B9-9B77-E346C1DA12F3} and have it not be deleted. Does anyone know how I can achieve this?</p>
  
  <p>Here's my script:</p>
  
  <pre><code>&lt;#
      This script uses VB script to identify which files need to be saved and then removes everything else.
  #&gt;
  
  $VBSFile = @"
  '' Identify which patches are registered on the system, and to which
  '' products those patches are installed.
  'Option Explicit
  Dim msi : Set msi = CreateObject("WindowsInstaller.Installer")
  'Output CSV header
  WScript.Echo "The data format is ProductCode, PatchCode, PatchLocation"
  Set objFSO = CreateObject("Scripting.FileSystemObject")
  Set objFile = objFSO.CreateTextFile("output.txt", True)
  objFile.WriteLine "ProductCode, PatchCode, PatchLocation"
  objFile.WriteLine ""
  ' Enumerate all products
  Dim products : Set products = msi.Products
  Dim productCode
  For Each productCode in products
      ' For each product, enumerate its applied patches
      Dim patches : Set patches = msi.Patches(productCode)
      Dim patchCode
      For Each patchCode in patches
          ' Get the local patch location
          Dim location : location = msi.PatchInfo(patchCode, "LocalPackage")
          objFile.WriteLine productCode &amp; ", " &amp; patchCode &amp; ", " &amp; location
  
      Next
  Next
  WScript.Echo "Data written to output.txt, these are the registered objects and SHOULD be kept!"
  "@
  
  $VBSFile | Set-Content .\WiMsps.vbs
  
  cscript .\WiMsps.vbs 
  
  $savelist = Import-Csv .\output.txt
  
  $filelocation = $savelist | select -ExpandProperty PatchLocation
  
  #First pass to remove exact file names
  dir C:\windows\Installer -file | ForEach-Object{
      $fullname = $_.FullName
      if($filelocation | Where-Object{$_ -like "*$fullname*"}){
          "Keeping $fullname"
      }
      else{
          Remove-Item $fullname -Force -Verbose
      }
  
  
  }
  
  #second pass to match product and patch codes
  dir C:\windows\Installer -Directory | ForEach-Object{
      $fullname = $_.name
      if($savelist | Where-Object{$_.ProductCode -like "*$fullname*" -or $_.PatchCode -like "*$fullname*" }){
          "Keeping $fullname"
      }
      else{
          Remove-Item $_.fullname -Force -Verbose -Recurse
      }
  
  }
  pause
  </code></pre>
  
  <p>Basically right now it's deleting everything it can't find a source for dependency. Or at least I think it is... I got this script from someone else, so yeah basically I can't figure out what to do.  </p>