How to safely delete orphaned patches (C:\Windows\Installer)
Aus Wiki-WebPerfect
<# This script uses Heath Stewart's VB script to identify which files need to be saved and then removes everything else. Can be run locally or pushed to remove servers with PSRemoting or PSexec. Requires to be ran as administrator. #> #Heath Stewart's VB script from # http://blogs.msdn.com/b/heaths/archive/2007/01/31/how-to-safely-delete-orphaned-patches.aspx $VBSFile = @" '' Identify which patches are registered on the system, and to which '' products those patches are installed. '' '' Copyright (C) Microsoft Corporation. All rights reserved. '' '' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY '' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE '' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A '' PARTICULAR PURPOSE. '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 & ", " & patchCode & ", " & 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 } }
Source: http://www.bryanvine.com/2015/06/powershell-script-cleaning-up.html