Here is a script that will delete Cisco Jabber conversations. If you are in an environment where you do not want these conversations to be saved and recoverable, this tool with taking care of it.
I wrote this tool so that it will kill the CiscoJabber process first and then deletes the appropriate file that stores the conversation. It will then restart Jabber. We set this up to execute when a user logs on and logs off. We have the script setup to make three passes of deletion.
We chose to use SDelete after reading this article on how much better SDelete is at cleaning up files on both SSD and HDD drives. You can download SDelete from here. The script is set up to execute SDelete.exe when it resides in the same location as the script.
Here is a video I took of the script executing. You can see the script closes jabber, deletes the associated .DB file, and then reopens Jabber. It must shut down Jabber to unlock the .DB file for deletion.
I have included examples of executing the script in the script documentation. As you can see in the script, I have set the SecureDeletePasses to 3, which can either be changed or overridden by defining it in the parameter at the time the script is executed.
UPDATE 1:
I came back and updated this script so that it will now parse through all user profiles and securely delete the appropriate files. Another change made is with the sdelete.exe file. A GPO is now used to do the following:
UPDATE 2:
I updated this script to function as a one-liner in case you want to run this as the end-user at logon, logoff, etc, which is what I have ended up doing. I also split this off into two one-liners. One is for a secured delete using sdelete64.exe and the other uses Remove-Item.
Secured Delete One-Liner:
I wrote this tool so that it will kill the CiscoJabber process first and then deletes the appropriate file that stores the conversation. It will then restart Jabber. We set this up to execute when a user logs on and logs off. We have the script setup to make three passes of deletion.
We chose to use SDelete after reading this article on how much better SDelete is at cleaning up files on both SSD and HDD drives. You can download SDelete from here. The script is set up to execute SDelete.exe when it resides in the same location as the script.
Here is a video I took of the script executing. You can see the script closes jabber, deletes the associated .DB file, and then reopens Jabber. It must shut down Jabber to unlock the .DB file for deletion.
I have included examples of executing the script in the script documentation. As you can see in the script, I have set the SecureDeletePasses to 3, which can either be changed or overridden by defining it in the parameter at the time the script is executed.
UPDATE 1:
I came back and updated this script so that it will now parse through all user profiles and securely delete the appropriate files. Another change made is with the sdelete.exe file. A GPO is now used to do the following:
- Push the sdelete.exe or sdelete64.exe file to all systems in the %WINDIR%\System32 directory. I use a GPO to push this file to the %Windir%\System32 directory so that it is available everywhere on the system in the event I want to do a secure delete on anything else.
- Push the .PS1 script to the designated directory on the computer so it can be executed locally without network connectivity. I also use the same GPO to push this file down.
- Create a scheduled task to execute the .PS1 file on the system at the designated interval. This is also created by a GPO.
You can download the script from my GitHub site located here.
I updated this script to function as a one-liner in case you want to run this as the end-user at logon, logoff, etc, which is what I have ended up doing. I also split this off into two one-liners. One is for a secured delete using sdelete64.exe and the other uses Remove-Item.
Secured Delete One-Liner:
powershell.exe -command "&{$Deletes='3';Get-Process -Name CiscoJabber -ErrorAction SilentlyContinue | Stop-Process;Do {$Process = Get-Process -Name CiscoJabber -ErrorAction SilentlyContinue} While ($Process -ne $null);Get-childItem -Path $Env:LOCALAPPDATA'\Cisco\Unified Communications\Jabber\CSF\History' -Filter *.db | ForEach-Object {$arguments='-accepteula'+[char]32+'-p'+[char]32+$Deletes+[char]32+[char]34+$_.FullName+[char]34;Start-Process -FilePath $env:windir'\System32\sdelete64.exe' -ArgumentList $Arguments -WindowStyle Hidden};Get-Item -Path $env:USERPROFILE'\Documents\MyJabberFiles' -ErrorAction SilentlyContinue | Where-Object {$arguments='-accepteula'+[char]32+'-p'+[char]32+$Deletes+[char]32+[char]34+$_.FullName+[char]34;Start-Process -FilePath $env:windir'\System32\sdelete64.exe' -ArgumentList $Arguments -WindowStyle Hidden};Start-Process -FilePath (Get-ChildItem -Path $env:ProgramFiles,${env:ProgramFiles(x86)} -Filter CiscoJabber.exe -Recurse -ErrorAction SilentlyContinue).FullName}"
Unsecured Delete One-Liner
powershell.exe -command "&{Get-Process -Name CiscoJabber -ErrorAction SilentlyContinue | Stop-Process;Do {$Process = Get-Process -Name CiscoJabber -ErrorAction SilentlyContinue} While ($Process -ne $null);Get-childItem -Path $Env:LOCALAPPDATA'\Cisco\Unified Communications\Jabber\CSF\History' -Filter *.db | ForEach-Object { Remove-Item -Path $_.FullName -Force };Get-Item -Path $env:USERPROFILE'\Documents\MyJabberFiles' -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force;Start-Process -FilePath (Get-ChildItem -Path $env:ProgramFiles,${env:ProgramFiles(x86)} -Filter CiscoJabber.exe -Recurse -ErrorAction SilentlyContinue).FullName}"
Main Script:
<#
.SYNOPSIS
Delete Cisco Jabber Chat History
.DESCRIPTION
Deletes the files and folder that contain the Cisco Jabber chat history
.PARAMETER SecureDelete
Implement Secure Deletion of files and folders
.PARAMETER SecureDeletePasses
Number of secure delete passes
.EXAMPLE
Delete Cisco Jabber chat without secure delete
powershell.exe -file CiscoJabberChatCleanup.ps1
Delete Cisco Jabber chate with secure delete
powershell.exe -file CiscoJabberChatCleanup.ps1 -SecureDelete -SecureDeletePasses 3
.NOTES
===========================================================================
Created with: SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.3.131
Created on: 12/13/2016 12:20 PM
Updated on: 12/27/2018 3:34 PM
Created by: Mick Pletcher
Filename: CiscoJabberChatCleanup.ps1
===========================================================================
#>
[CmdletBinding()]
param
(
[switch]$SecureDelete,
[string]$SecureDeletePasses = '3'
)
function Close-Process {
<#
.SYNOPSIS
Stop ProcessName
.DESCRIPTION
Kills a ProcessName and verifies it was stopped while reporting it back to the screen.
.PARAMETER ProcessName
Name of ProcessName to kill
.EXAMPLE
PS C:\> Close-ProcessName -ProcessName 'Value1'
.NOTES
Additional information about the function.
#>
[CmdletBinding()][OutputType([boolean])]
param
(
[ValidateNotNullOrEmpty()][string]$ProcessName
)
$Process = Get-Process -Name $ProcessName -ErrorAction SilentlyContinue
If ($Process -ne $null) {
$Output = "Stopping " + $Process.Name + " process....."
Stop-Process -Name $Process.Name -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
$TestProcess = Get-Process $ProcessName -ErrorAction SilentlyContinue
If ($TestProcess -eq $null) {
$Output += "Success"
Write-Host $Output
Return $true
} else {
$Output += "Failed"
Write-Host $Output
Return $false
}
} else {
Return $true
}
}
function Get-Architecture {
<#
.SYNOPSIS
Get-Architecture
.DESCRIPTION
Returns whether the system architecture is 32-bit or 64-bit
.EXAMPLE
Get-Architecture
.NOTES
Additional information about the function.
#>
[CmdletBinding()][OutputType([string])]
param ()
$OSArchitecture = Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture
$OSArchitecture = $OSArchitecture.OSArchitecture
Return $OSArchitecture
#Returns 32-bit or 64-bit
}
function Get-RelativePath {
<#
.SYNOPSIS
Get the relative path
.DESCRIPTION
Returns the location of the currently running PowerShell script
.NOTES
Additional information about the function.
#>
[CmdletBinding()][OutputType([string])]
param ()
$Path = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent) + "\"
Return $Path
}
function Open-Application {
<#
.SYNOPSIS
Open Application
.DESCRIPTION
Opens an applications
.PARAMETER Executable
A description of the Executable parameter.
.PARAMETER ApplicationName
Display Name of the application
.PARAMETER Process
Application Process Name
.EXAMPLE
PS C:\> Open-Application -Executable 'Value1'
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
param
(
[string]$Executable,
[ValidateNotNullOrEmpty()][string]$ApplicationName
)
$Architecture = Get-Architecture
$Uninstall = Get-ChildItem -Path REGISTRY::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
If ($Architecture -eq "64-bit") {
$Uninstall += Get-ChildItem -Path REGISTRY::"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
}
$InstallLocation = ($Uninstall | ForEach-Object { Get-ItemProperty $_.PsPath } | Where-Object { $_.DisplayName -eq $ApplicationName }).InstallLocation
If ($InstallLocation[$InstallLocation.Length - 1] -ne "\") {
$InstallLocation += "\"
}
$Process = ($Executable.Split("."))[0]
$Output = "Opening $ApplicationName....."
Start-Process -FilePath $InstallLocation$Executable -ErrorAction SilentlyContinue
Start-Sleep -Seconds 5
$NewProcess = Get-Process $Process -ErrorAction SilentlyContinue
If ($NewProcess -ne $null) {
$Output += "Success"
} else {
$Output += "Failed"
}
Write-Output $Output
}
function Remove-ChatFiles {
<#
.SYNOPSIS
Delete Jabber Chat Files
.DESCRIPTION
Deletes Jabber chat files located at %USERNAME%\AppData\Local\Cisco\Unified Communications\Jabber\CSF\History and verifies they were deleted
.EXAMPLE
PS C:\> Remove-ChatFiles
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
param ()
$Users = Get-ChildItem -Path $env:HOMEDRIVE"\users" -Exclude 'Administrator', 'public', 'iCreateService', 'sccmadmin', 'Default'
foreach ($User in $Users) {
#Get Jabber Chat history files
$History = $User.FullName + '\AppData\Local\Cisco\Unified Communications\Jabber\CSF\History'
$ChatHistoryFiles = Get-ChildItem -Path $History -Filter *.db
If ($ChatHistoryFiles -ne $null) {
foreach ($File in $ChatHistoryFiles) {
$Output = "Deleting " + $File.Name + "....."
If ($SecureDelete.IsPresent) {
$RelativePath = Get-RelativePath
$sDelete = [char]34 + $env:windir + "\system32\" + "sdelete64.exe" + [char]34
$Switches = "-accepteula -p" + [char]32 + $SecureDeletePasses + [char]32 + "-q" + [char]32 + [char]34 + $File.FullName + [char]34
$ErrCode = (Start-Process -FilePath $sDelete -ArgumentList $Switches -Wait -PassThru).ExitCode
If (($ErrCode -eq 0) -and ((Test-Path $File.FullName) -eq $false)) {
$Output += "Success"
} else {
$Output += "Failed"
}
} else {
Remove-Item -Path $File.FullName -Force | Out-Null
If ((Test-Path $File.FullName) -eq $false) {
$Output += "Success"
} else {
$Output += "Failed"
}
}
Write-Output $Output
}
} else {
$Output = "No Chat History Present"
Write-Output $Output
}
}
}
function Remove-MyJabberFilesFolder {
<#
.SYNOPSIS
Delete MyJabberFiles Folder
.DESCRIPTION
Delete the MyJabberFiles folder stores under %USERNAME%\documents and verifies it was deleted.
.EXAMPLE
PS C:\> Remove-MyJabberFilesFolder
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
param ()
$Users = Get-ChildItem -Path $env:HOMEDRIVE"\users" -Exclude 'Administrator', 'public', 'iCreateService', 'sccmadmin', 'Default'
foreach ($User in $Users) {
$Folder = $User.FullName + '\Documents\MyJabberFiles'
$MyJabberFilesFolder = Get-Item $Folder -ErrorAction SilentlyContinue
If ($MyJabberFilesFolder -ne $null) {
$Output = "Deleting " + $MyJabberFilesFolder.Name + "....."
Remove-Item -Path $MyJabberFilesFolder -Recurse -Force | Out-Null
If ((Test-Path $MyJabberFilesFolder.FullName) -eq $false) {
$Output += "Success"
} else {
$Output += "Failed"
}
Write-Output $Output
} else {
$Output = "No MyJabberFiles folder present"
Write-Output $Output
}
}
}
Clear-Host
#Kill Cisco Jabber Process
$JabberClosed = Close-Process -ProcessName CiscoJabber
#Delete .DB files from each %USERNAME%\AppData\Local\Cisco\Unified Communications\Jabber\CSF\History
Remove-ChatFiles
#Delete each %USERNAME%\documents\MyJabberFiles directory
Remove-MyJabberFilesFolder
#Reopen Jabber if it was open
If ($JabberClosed -eq $true) {
Open-Application -ApplicationName "Cisco Jabber" -Executable CiscoJabber.exe
}
Great Post! Another handy trick is, once the database is deleted and the file recreated on launch, mark the file as "read-only". This will prevent future conversations from being logged.
ReplyDeleteHi Charles and Mick,
ReplyDeleteNice post. Congratulations for help.