Skip to content

Instantly share code, notes, and snippets.

@Bill-Stewart
Created August 25, 2025 14:15
Show Gist options
  • Save Bill-Stewart/5446ca84167a30d89d46cb984d65a0f6 to your computer and use it in GitHub Desktop.
Save Bill-Stewart/5446ca84167a30d89d46cb984d65a0f6 to your computer and use it in GitHub Desktop.
<#
Clear-SmartcardCache.ps1
Written by Bill Stewart
We have seen some instances where a user gets a new smartcard certificate and
they are unable to log on due to cached data in the local registry.
The purpose of this script is to remove this cached data from the registry
to fix this prompt. The script makes a backup copy of the registry subkey to
a user-selectable folder before it deletes anything.
1. Uses reg.exe to make a backup copy of the registry subkey containing the
cached data to a user-selectable folder
2. Stops the following services:
* CertPropSvc (Certificate Propagation)
* SCardSvr (Smart card)
3. Removes the following registry value:
* Key: HKEY_LOCAL_MACHINE
* Subkey: SOFTWARE\Microsoft\Cryptography\Calais\Cache
* Value: Cache
4. Prompts to reboot the computer
Version history:
2025-08-25
* Initial version
#>
#requires -version 3
#requires -RunAsAdministrator
[CmdletBinding()]
param(
[String]
$BackupPath,
[Switch]
$NonInteractive,
[Switch]
$Overwrite
)
$SCRIPT_TITLE = "Clear Smartcard Cache"
$BACKUP_FILE_NAME = "CachedSmartcardData.reg"
$REG_SUBKEY = "SOFTWARE\Microsoft\Cryptography\Calais\Cache"
$REG_VALUE = "Cache"
$WINDOWS_FOLDER = [Environment]::GetFolderPath([Environment+SpecialFolder]::Windows)
$ERROR_FILE_NOT_FOUND = 2
$ERROR_PATH_NOT_FOUND = 3
$ERROR_ALREADY_EXISTS = 183
$ERROR_CANCELLED = 1223
$MB_YESNO = 4
$MB_ICONERROR = 0x10
$MB_ICONQUESTION = 0x20
$MB_ICONINFORMATION = 0x40
$MB_DEFBUTTON2 = 0x100
$MB_IDYES = 6
$wshShell = New-Object -ComObject "WScript.Shell"
function OutMessage {
param(
[String]
$message
)
if ( $NonInteractive ) {
Write-Host $message
}
else {
$null = $wshShell.Popup($message,0,$SCRIPT_TITLE,$MB_ICONINFORMATION)
}
}
function OutError {
param(
[String]
$message,
[Management.Automation.ErrorCategory]
$category
)
if ( $NonInteractive ) {
Write-Error $message -Category $category
}
else {
$null = $wshShell.Popup($message,0,$SCRIPT_TITLE,$MB_ICONERROR)
}
}
function BrowseFolder {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[String]
$dialogTitle,
[Parameter(Position = 1)]
[String]
$initialDirectory,
[Parameter(Position = 2)]
[Switch]
$showNewFolderButton
)
$BIF_RETURNONLYFSDIRS = 0x01
$BIF_NEWDIALOGSTYLE = 0x40
$BIF_NONEWFOLDERBUTTON = 0x200
$options = $BIF_RETURNONLYFSDIRS -bor $BIF_NEWDIALOGSTYLE
if ( -not $showNewFolderButton ) {
$options = $options -bor $BIF_NONEWFOLDERBUTTON
}
[IntPtr] $hWnd = [Diagnostics.Process]::GetCurrentProcess().MainWindowHandle
try {
$shellApp = New-Object -ComObject Shell.Application
$folder = $shellApp.BrowseForFolder($hWnd,$dialogTitle,$options,$initialDirectory)
if ( $null -ne $folder ) {
$folder.Self.Path
}
}
catch {
}
}
function TestRegistryValue {
param(
[String]
$path,
[String]
$value
)
$null -ne (Get-ItemProperty $Path $value -ErrorAction SilentlyContinue)
}
if ( -not (TestRegistryValue "HKLM:\$REG_SUBKEY" $REG_VALUE) ) {
$message = "Smartcard cache registry value already cleared."
OutMessage $message
exit
}
$reg = Join-Path (Join-Path $WINDOWS_FOLDER "System32") "reg.exe"
if ( -not (Test-Path $reg) ) {
OutError "File not found - '$reg'" "ObjectNotFound"
exit $ERROR_FILE_NOT_FOUND
}
if ( -not $BackupPath ) {
if ( $NonInteractive ) {
$BackupPath = $WINDOWS_FOLDER
}
else {
$params = @{
dialogTitle = "Select folder for smartcard cache backup file"
initialDirectory = $WINDOWS_FOLDER
}
$BackupPath = BrowseFolder @params
if ( -not $BackupPath ) { exit }
}
}
else {
$BackupPath = (Resolve-Path $BackupPath -ErrorAction SilentlyContinue).ProviderPath
}
if ( -not (Test-Path $BackupPath) ) {
OutError "Backup folder not found - '$BackupPath'" "ObjectNotFound"
exit $ERROR_PATH_NOT_FOUND
}
$BackupFilePath = Join-Path $BackupPath $BACKUP_FILE_NAME
if ( Test-Path $BackupFilePath ) {
if ( $NonInteractive ) {
if ( -not $Overwrite ) {
Write-Host "Smartcard cache backup file already exists."
exit $ERROR_ALREADY_EXISTS
}
}
else {
if ( $wshShell.Popup("Smartcard cache backup file already exists. Overwrite?",
0,$SCRIPT_TITLE,$MB_YESNO -bor $MB_ICONQUESTION -bor $MB_DEFBUTTON2) -ne $MB_IDYES ) {
exit $ERROR_CANCELLED
}
}
}
& $reg EXPORT "HKLM\$REG_SUBKEY" $BackupFilePath /y
$result = $LASTEXITCODE
if ( $result -ne 0 ) {
OutError ("REG EXPORT command returned error code {0}" -f $result) "InvalidResult"
exit $result
}
if ( -not (Test-Path $BackupFilePath) ) {
OutError "Smartcard cache backup file not found - '$BackupFilePath'" "ObjectNotFound"
exit $ERROR_FILE_NOT_FOUND
}
$serviceNames = "CertPropSvc","SCardSvr"
$serviceNames | Stop-Service -Verbose
Remove-ItemProperty "HKLM:\$REG_SUBKEY" $REG_VALUE -ErrorAction SilentlyContinue
if ( TestRegistryValue "HKLM:\$REG_SUBKEY" $REG_VALUE ) {
$errorMessage = "Registry value not removed - 'HKLM\$REG_SUBKEY\$REG_VALUE'"
OutError $errorMessage "ResourceExists"
exit $ERROR_ALREADY_EXISTS
}
if ( -not $NonInteractive ) {
$answer = $wshShell.Popup("Reboot now?",
0,$SCRIPT_TITLE,$MB_YESNO -bor $MB_ICONQUESTION -bor $MB_DEFBUTTON2)
}
else {
$answer = $MB_IDYES
}
if ( $answer -eq $MB_IDYES ) {
Restart-Computer -Force
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment