A few months back, I had built what I dubbed the “Ultimate Oracle Client Deinstaller.” It could handle the deinstallation of Oracle database clients 11g, 12c, and 19c to include having multiple clients installed- even if they share the same Oracle_Home location.
Recently, I ran into some alternate configurations of the Oracle client that required some contingent action to be added to the script to accommodate. Another issue I ran into- a broken Oracle client. In this instance, the deinstall procedure is just simply not going to execute properly. To account for this scenario, I ensured that the script will complete the “manual” deinstall procedure automatically.
# Clear variables for repeatability
Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0
# Function to set environment variables for all levels
Function Set-EnvVar {
param (
$EnvVarName,
$EnvVarValue
)
[System.Environment]::SetEnvironmentVariable($EnvVarName,$EnvVarValue,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable($EnvVarName,$EnvVarValue,[System.EnvironmentVariableTarget]::User)
[System.Environment]::SetEnvironmentVariable($EnvVarName,$EnvVarValue,[System.EnvironmentVariableTarget]::Process)
} # End of set environment variables function
# Refresh Environment Variables Function
Function Refresh-Env {
# Clear nullified environment variables
$machineValues = [Environment]::GetEnvironmentVariables('Machine')
$userValues = [Environment]::GetEnvironmentVariables('User')
$processValues = [Environment]::GetEnvironmentVariables('Process')
# Identify the entire list of environment variable names first
$envVarNames = ($machineValues.Keys + $userValues.Keys + 'PSModulePath') | Sort-Object | Select-Object -Unique
# Lastly remove the environment variables that no longer exist
ForEach ($envVarName in $processValues.Keys | Where-Object {$envVarNames -like $null}) {
Remove-Item -LiteralPath "env:${envVarName}" -Force
}
# Update variables
foreach($level in "Machine","User","Process") {
[Environment]::GetEnvironmentVariables($level)
}
} # End of refresh environment variables function
# Deinstall-Oracle Function
Function Deinstall-Oracle {
# Look for "Oracle" directory on system drive
$OracleDir = dir -Path "$env:SystemDrive\Oracle*" | Select -ExpandProperty "FullName"
# If Oracle directory is present...
if ($OracleDir -ne $null){
# For each "Oracle" directory instance
ForEach ($instance in $OracleDir) {
# If Deinstall_Oracle directory does not exist, create it
$Deinstall_Oracle = "$env:SystemDrive\Deinstall_Oracle\"
If (!(Test-Path $Deinstall_Oracle)){
New-Item -Path "$Deinstall_Oracle" -ItemType Directory -Force
}
# Establish product path
$ProdPath = Join-Path $instance '\product'
# Establish base32 path
$Base32Path = Join-Path $instance '\base32'
# Check for product path
If (Test-Path $ProdPath) {
# Set base path to "product"
$BasePath = $ProdPath
# Get home directory
$HomePath = dir -Path $BasePath -Filter '*.*.*' -Recurse | Where-Object {$_.PSIsContainer -eq $True -and $_.FullName -notlike '*client*'} | Select -ExpandProperty "FullName"
# Check for base32 path
} Elseif (Test-Path $Base32Path) {
# Set base path to "base32"
$BasePath = $Base32Path
# Get home directory
$HomePath = dir -Path $BasePath -Filter 'client*' -Recurse | Where-Object {$_.PSIsContainer -eq $True -and $_.FullName -notlike '*jdk*'} | Select -ExpandProperty "FullName"
}
# For each deinstall directory instance within Oracle directory instance...
ForEach ($homedir in $HomePath) {
# Get home directory
$HomeLeaf = Split-Path $homedir -Leaf
# Check for deinstall directory instances within home directory
$DeinstallDir = dir -Path $homedir -Filter 'deinstall' -Recurse | Where-Object {$_.PSIsContainer -eq $True -and $_.FullName -notlike '*inventory*'} | Select -ExpandProperty "FullName"
# Get Deinstall.bat path and filter alternative locations
$DeinstallBatch = dir -Path $DeinstallDir -Filter 'deinstall.bat' | Where-Object {$_ -notlike '*inventory*'} | Select -ExpandProperty "FullName"
# If Deinstall.bat exists...
If ($DeinstallBatch -ne $null) {
# Create subdirectory in Deinstall_Oracle directory
$subDir = Join-Path $Deinstall_Oracle $HomeLeaf
New-Item -Path $subDir -ItemType Directory -Force
# Create .RSP file in subdirectory using deinstall.bat
Start-Process -FilePath "$DeinstallBatch" -Wait -NoNewWindow -ArgumentList "-silent -checkonly -o $subDir"
# Execute deinstall.bat using .RSP file
$RSP = Join-Path $subDir '\deinstall*.rsp'
Start-Process -FilePath "$DeinstallBatch" -Wait -NoNewWindow -ArgumentList "-silent -paramfile $RSP"
}
}
# Remove Oracle* directory instances
Remove-Item -Path $instance -Force -Recurse -ErrorAction SilentlyContinue
}
# Remove Deinstall_Oracle directory
Remove-Item -Path $Deinstall_Oracle -Force -Recurse -ErrorAction SilentlyContinue
}
# Remove Program Files
$ProgFiles = "$env:SystemDrive\Program Files\Oracle"
$ProgFilesx86 = "$env:SystemDrive\Program Files (x86)\Oracle"
If (Test-Path $ProgFiles) {
Remove-Item -Path $ProgFiles -Force -Recurse -ErrorAction SilentlyContinue
} Elseif (Test-Path $ProgFilesx86) {
Remove-Item -Path $ProgFilesx86 -Force -Recurse -ErrorAction SilentlyContinue
}
} # End of Deinstall-Oracle function
# Clean up Registry Function
Function Remove-RegKey {
param (
$Reg
)
$Reg = $Reg
Remove-Item -Path "Registry::$Reg" -Force -Recurse
} # End of registry clean up function
# Call Deinstall-Oracle function
Deinstall-Oracle
# Use Set-EnvVar function to clear environment variables
Set-EnvVar -EnvVarName "TNS_Admin" -EnvVarValue "$null"
Set-EnvVar -EnvVarName "_JAVA_OPTIONS" -EnvVarValue "$null"
Set-EnvVar -EnvVarName "ORACLE_HOME" -EnvVarValue "$null"
# Execute Refresh-Env function
Refresh-Env
# Call Registry Function
Remove-RegKey -Reg "HKEY_LOCAL_MACHINE\SOFTWARE\Oracle*"
Remove-RegKey -Reg "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Oracle*"
Remove-RegKey -Reg "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Oracle*"
Hi Payton,
Thanks for the nice script. Possible for you to provide the above script for multiple servers. We would like to uninstall oracle client from 500 servers.
Good evening,
I can indeed modify this script to execute on multiple systems. I have deployed it using MECM (SCCM) in the past, but it could be done directly with PowerShell. For this work, I would strongly encourage taking a staged approach at deployment. You can find my phone/email at https://paytonflint.com/contact.
Here is an untested update to the script that will allow for batch deployment: https://paytonflint.com/preliminary-batch-job-version-ultimate-oracle-client-deinstaller/
Thanks for updating the script.
No problem! Please let me know how it worked for you, I am interested in improving this script.
Hi Payton – Your script did not work for me on the single server itself. How do you execute the script? If you can provide the example that would be great.
Thanks.
Sure thing, I’ll publish a video demonstration.
Update + video demonstration: https://paytonflint.com/powershell-ultimateocd-update-demo/
Thanks!! I will try and give you my feedback.
Excellent, yes please do. I am interested in improving this script.
Is there a way to remove all Oracles but the 19 version? I need to remove all old versions on the device but leave the 19 vesion on. Thank you
I think I would “clean slate” the device and then reinstall 19c. If you really must not remove it, I think it would be possible. But, as-is, my script is not tailored for doing this. I would also like to direct you to the most current version of the script on my GitHub @ https://github.com/p8nflnt/UltimateOCD/blob/main/UltimateOCD.ps1