ConfigMgr Delete CCM & Nomad Cached Items

Updated 2018.05.31 to include script to Remove all software Updates from Nomad Cache.
Updated 2018.01.29 to include script to clean Nomad based on Content ID.

The CCMCache is pretty good at taking care of itself, but perhaps you have a reason to delete something specific, how do you do that in a supported way?

I have two scripts below, one that will just blow away ALL Software Updates in the cache, thoughts behind this, software updates should be installed within a couple weeks of being cached, after that, they are useless and never needed again, the other reason, if I’m upgrading to a new Windows 10 Build, I don’t need any of those old Windows 10 Software Updates in my cache anymore. (yes, you probably have others in there from office, etc, but hopefully you’ve installed them already, I admit, this isn’t for everyone) Script Name:
Remove-CCMCacheSoftwareUpdateContent.ps1Script 2, delete specific items based on ContentID.  This is more for when you have a package / app you just want gone, perhaps you’re never going to deploy it again, or perhaps, someone accidently put a domain admin username & password in the script that’s now in the package sitting on all of our workstation ccmcache’s.  Instead of dumping the entire cache, you can target a specific content and delete it.  I also use this for deleting the Windows 10 Upgrade Media from the CCMCache after the upgrade.  Normally you wouldn’t need to clean up after your task sequence, but if you precache your payloads into the ccmcache to speed up your actual deployment, then you’ll have that package contents just taking up space. Script Name:
Remove-CCMCacheContent.ps1

Flipside, Reasons to just leave it alone…  once you fill up your CCMCache, it’s YOURS!  You own that 20GB or whatever your CCMCache size is.  No one can take that space away from you again.  If you clear it out, sure, your machine might have more available free space, then the user steals it with cat videos, and guess what, when you need to cache that Adobe Software install, you can’t, not enough storage on the machine, if you would have just left the cache full, it would have cleared out what it needed at the time of the request, and pulled down the installer content.

How am I using them?

I have a script that will dump all of the Software Updates in the Cache, I use it in my Upgrade TS if after several other remediation’s, still don’t have 20GB free space to start the Build upgrade.
imageimage

The other one, I have it clean up a couple packages at the end of the TS that are in the CCMCache from the PreCache TS:

image

Script is set to create a log in c:\windows\temp\ you can modify this to whatever you like.

Remove-CCMCacheSoftwareUpdateContent.ps1

<# 
.SYNOPSIS 
Delete Specified Item(s) From CCM Cache
.DESCRIPTION 
Uses ContentIDs to identify (ALL SOFTWARE UPDATES) and purge content from the local ccm cache - Created by Gary Blok @gwblok
Partial Code borrowed from: https://gallery.technet.microsoft.com/scriptcenter/Deleting-the-SCCM-Cache-da03e4c7
Assist by Keith S. Garner @keithga1
.LINK
https://garytown.com
#> 
   
$Logfile = "c:\windows\temp\Remove-CCMCacheContent.log"
# Connect to resource manager COM object    
$CMObject = New-Object -ComObject 'UIResource.UIResourceMgr' 
 
# Using GetCacheInfo method to return cache properties 
$CMCacheObjects = $CMObject.GetCacheInfo() 
 
# Delete Cache item 
$CMCacheObjects.GetCacheElements() | Where-Object { $_.ContentID | Select-String -Pattern '^[\dA-F]{8}-(?:[\dA-F]{4}-){3}[\dA-F]{12}$' }   | ForEach-Object { 
    $CMCacheObjects.DeleteCacheElement($_.CacheElementID)
    Add-Content $Logfile -value "Deleted: Name: $($_.ContentID)  Version: $($_.ContentVersion)"
    Write-Host "Deleted: Name: $($_.ContentID)  Version: $($_.ContentVersion)" -BackgroundColor Red 
}   

Remove-CCMCacheContent.ps1

<# 
.SYNOPSIS 
Delete Specified Item(s) From CCM Cache
.DESCRIPTION 
Uses ContentIDs to identify and purge content from the local ccm cache - Created by Gary Blok @gwblok
Partial Code borrowed from: https://gallery.technet.microsoft.com/scriptcenter/Deleting-the-SCCM-Cache-da03e4c7
Assist by Mark Godfrey @Geodesicz
.PARAMETER CachItemsToDelete
Comma separated values for the Content ID(s) of the cach item(s) to delete
.EXAMPLE 
.\Remove-CCMCacheContent.ps1 -CacheItemsToDelete "PS100123","20eb8ec8-0b7e-4831-a5ae-95680b11e6b5","PS111197"
.LINK
https://garytown.com
#> 

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,Position=1,HelpMessage="ContentIDs")]
    [ValidateNotNullOrEmpty()]
    [String[]]$CacheItemsToDelete
)
#$CacheItemsToDelete = "PS100002","20eb8ec8-0b7e-4831-a5ae-95680b11e6b5","decbb5fe-1cbc-4984-bbf2-e76347150135"

$Logfile = "c:\windows\temp\Remove-CCMCacheContent.log"
# Connect to resource manager COM object    
$CMObject = New-Object -ComObject 'UIResource.UIResourceMgr' 
 
# Using GetCacheInfo method to return cache properties 
$CMCacheObjects = $CMObject.GetCacheInfo() 
 
# Delete Cache item 
$CMCacheObjects.GetCacheElements() | Where-Object {$_.ContentID -in $CacheItemsToDelete} | ForEach-Object { 
    #$CMCacheObjects.DeleteCacheElement($_.CacheElementID)
    Add-Content $Logfile -value "Deleted: Name: $($_.ContentID)  Version: $($_.ContentVersion)"
    Write-Host "Deleted: Name: $($_.ContentID)  Version: $($_.ContentVersion)" -BackgroundColor Red 
}

Added 2018.01.29 – Remove-NomadCacheContent.ps1 (works the same as Remove-CCMCacheContent.ps1)

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,Position=1,HelpMessage="ContentIDs")]
    [ValidateNotNullOrEmpty()]
    [String[]]$CacheItemsToDelete
)
ForEach ($CacheItemsToDelete in $CacheItemsToDelete)
{
$pkgver = (Get-ItemPropertyValue "HKLM:\SOFTWARE\1E\NomadBranch\PkgStatus\$CacheItemsToDelete" 'version')
cmd.exe /c "CacheCleaner.exe -deletepkg=$CacheItemsToDelete -pkgver=$pkgver"
}

Added 2018.01.29 – Remove-NomadCacheSoftwareUpdateContent.ps1 (works the same as Remove-CCMCacheSoftwareUpdateContent.ps1)

$NomadCachePath = get-itempropertyvalue -path 'HKLM:\Software\1E\NomadBranch' -name 'LocalCachePath' | Write-Output
$NomadInstallPath = get-itempropertyvalue -path 'HKLM:\Software\1E\NomadBranch' -name 'InstallationDirectory' | Write-Output
$Folder = '*_cache'
$TotalNomadDiskSize  = get-childitem (join-path ($NomadCachePath) $Folder) -recurse -ErrorAction SilentlyContinue | measure-object -Sum length | % sum | write-output
$exclude = @("ContentDeliveryGUID","ReturnStatus","ElapsedSeconds","BackOffSeconds")

$NomadPackages =

    foreach ( $Pkg in get-childitem HKLM:\software\1e\NomadBranch\PkgStatus ) {

        $pkg | Get-ItemProperty |
            Select-Object -Property *,@{ Name = 'ActualSize'; expression = {
                Get-TotalNomadDiskSize -folder "$($_.PSChildName)_Cache" 
            } } -ExcludeProperty $exclude
   }

$SoftwareUpdates = $NomadPackages | where-object { $_.PSChildName | Select-String -Pattern '^[\dA-F]{8}-(?:[\dA-F]{4}-){3}[\dA-F]{12}$' } | write-output

Write-Host "Before Deleting Updates Nomad Cache size: $TotalNomadDiskSize" -ForegroundColor Green

ForEach ($SoftwareUpdates  in $SoftwareUpdates)
    {
    $SoftwareUpdatesContentLocation = ($SoftwareUpdates).PSChildName
    $SoftwareUpdatesContentVersion = ($SoftwareUpdates).Version
    Write-Host "Deleting: $SoftwareUpdatesContentLocation version: $SoftwareUpdatesContentVersion" -ForegroundColor Green
    cmd.exe /c """$NomadInstallPath\CacheCleaner.exe"" -deletepkg=$SoftwareUpdatesContentLocation -pkgver=$SoftwareUpdatesContentVersion"
    Write-Host "Deleted: $SoftwareUpdatesContentLocation version: $SoftwareUpdatesContentVersion" -ForegroundColor Yellow
    }

$TotalNomadDiskSize  = get-childitem (join-path ($NomadCachePath) $Folder) -recurse -ErrorAction SilentlyContinue | measure-object -Sum length | % sum | write-output
Write-Host "Current Nomad Cache size: $TotalNomadDiskSize" -ForegroundColor Green

In Action:
image
as you can see, it deletes every version of the content id. AKA, if the client cached version 1 of the package, then you updated the package with a new file, the client could then download version 2 of the same package.  Running this script will dump every version of that same package.

Nomad Cleanup In Action (if you pick a package that isn’t on the machine, it gives the errors about not finding it, and continues on)

Nomad Software Update Clean

Feel free to use them however you want, I just tend to live in the Task Sequence world now, so that’s how I use them.

Thanks to Mark Godfrey, Keith Garner & the PS Gallery, see actual scripts for more details.

13 thoughts on “ConfigMgr Delete CCM & Nomad Cached Items”

  1. Nice work and useful.

    You might also want to look into removing the old version of Windows. This is achieved via Disk CleanUp. The Disk CleanUp utility in storage spaces was updated in 1709 and should further advance in 1803.

    Reply
  2. @gwblok is there away to tweak your Remove-NomadCacheContent.ps1 script so that it can delete just Microsoft Updates instead of deleting everything in the nomad cache? Thanks!

    Reply
    • Done, PLEASE TEST before you deploy, I whipped this together pretty quick (updated in above post), stealing a little code from Keith Garner. 🙂
      A much MUCH nicer version will be blogged by Keith Garner or Mike Terrill when they have time.

      Reply
  3. Ok I think I have fixed the first part.
    $((get-itemproperty -path “Registry::HKEY_LOCAL_MACHINE\Software\1E\NomadBranch”).LocalCachePath)

    Still reaching your Select-String -Pattern. I don’t think the pattern is correct for my environment.
    Here is an example. b4dd4aaf-ad1f-4eb8-856c-210c782f86cc_Cache

    Reply
  4. This seemed to work better for me. Tell me what you think? Thanks 🙂

    $NomadCachePath = $((get-itemproperty -path “Registry::HKEY_LOCAL_MACHINE\Software\1E\NomadBranch”).LocalCachePath) | Write-Output
    #Write-Host “Nomad Cache Directory is $NomadCachePath”
    $NomadInstallPath = $((get-itemproperty -path “Registry::HKEY_LOCAL_MACHINE\Software\1E\NomadBranch”).InstallationDirectory) | Write-Output
    #Write-Host “Nomad Install Directory is $NomadInstallPath”

    $SoftwareUpdates = gci “HKLM:\SOFTWARE\1E\NomadBranch\PkgStatus” | where-object { $_.PSChildName | Select-String -Pattern ‘^[\dA-F]{8}-(?:[\dA-F]{4}-){3}[\dA-F]{12}$’} | write-output

    ForEach ($SoftwareUpdates in $SoftwareUpdates){
    #Write-Host $SoftwareUpdates
    $SoftwareUpdatesContentLocation = ($SoftwareUpdates).PSChildName
    $SoftwareUpdatesContentVersion = $SoftwareUpdates.getvalue(“Version”)
    $SoftwareUpdatesDate = $SoftwareUpdates.getvalue(“FinishTimeUTC”)
    $SoftwareUpdatesDate = $SoftwareUpdatesDate.Substring(0,$SoftwareUpdatesDate.Length-9)

    If($SoftwareUpdatesDate -le ‘20180430’)
    {
    Write-Host “Deleting: $SoftwareUpdatesContentLocation version: $SoftwareUpdatesContentVersion” -ForegroundColor Green
    cmd.exe /c “””$NomadInstallPath\CacheCleaner.exe”” -deletepkg=$SoftwareUpdatesContentLocation -pkgver=$SoftwareUpdatesContentVersion”
    Write-Host “Deleted: $SoftwareUpdatesContentLocation version: $SoftwareUpdatesContentVersion” -ForegroundColor Yellow
    }
    }

    Reply
  5. Actually the cache clean cycle that is in 6.3 is very primitive. I tried to get them to take cache management seriously when I was there but they had more important priorities (i.e. tachyon). We ended up implementing my vision for cache management that is pretty sophisticated in terms of purging items based on type (something else I tried to get them to do is tag the type of content). This way you can control things based on how long it should be kept vs. doing a rather ‘dumb’ FIFO method.

    Reply
  6. I use this really simple matching method for updates

    If($PackageID -match “……..-….-….-……..” -or $PackageID -match “Content_……..-….-….-……..”)

    Reply
  7. cacheCleaner.exe is not purging/deleting content from CCM cache for every package even when I specify the correct -pkgver in the command. I’ve verified the pkgver in Nomad registry location, Nomad cache .LsZ file, and CCM cache.

    Anyone come across this before?

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.