Payton Flint's Tech Blog
Menu
  • Home
  • Blog
  • Categories
  • Resources
  • About
  • Contact
Menu

PowerShell- UltimateOCD Update + Demo

Posted on July 17, 2023July 17, 2023 by paytonflint

For the gentleman requesting assistance with my UltimateOCD script, I have revised it further to allow you to easily provide some parameters like the target directory, directory exclusions, and a custom temporary directory path. In addition, I have revised the logic to use the “product” & “x.x.x” (version number) directories to detect Oracle client instances. Previously, this was reliant on the Oracle Base directory name containing “Oracle,” which may not always be the case.

I have also created a video demonstration to help provide insight into the script’s function.

The script can be found here: https://github.com/p8nflint/UltimateOCD.git

Here is the updated script:

<# ULTIMATE ORACLE CLIENT DEINSTALLER ===============================================================================
Script written by Payton Flint
See https://paytonflint.com/powershell-ultimate-oracle-client-deinstaller/
Deinstalls 11g, 12c, 19c Oracle clients
#>

# Clear variables for repeatability
Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0

# Specify target directory
$TargetDrive = 'C:\'

# Directories to exclude
$ExcludeDirs = @("")

# Temporary Directory Path
$TempDir = "C:\Ultimate_OCD"
#====================================================================================================================
  
# Uninstall-Oracle Function
Function Uninstall-Oracle {
    param (
        $TargetDrive,
        $ExcludeDirs,
        $TempDir
    )
    # Exclude system directories
    $ExcludeDirs += @("PerfLogs", "Program Files", "Program Files (x86)", "Users", "Windows")
    # Create IncludeDirs array
    $IncludeDirs = @()
    # Get directories w/o exclusions
    $IncludeDirs += Get-ChildItem -Path $TargetDrive -Directory | Where-Object { $_.Name -notin $ExcludeDirs}
    # Append TargetDrive
    For ($i = 0; $i -lt $IncludeDirs.Count; $i++) {
        $IncludeDirs[$i] = Join-Path $TargetDrive $IncludeDirs[$i]
    }
    If ($IncludeDirs -ne $null) {
        # Get each instance of "product" directory from included directories
        $ProductPath = Get-ChildItem -Path $IncludeDirs -Recurse -Directory `
        | Where-Object { $_.Name -eq 'product' } `
        | Select -ExpandProperty "FullName"
        If ($ProductPath -ne $null) {
            # Create VersionPath array
            $VersionPath = @()
            # Get each instance of "x.x.x" version subdirectory from each ProductPath
            $ProductPath | ForEach-Object {
                $VersionPath += Get-ChildItem -Path $_ -Recurse -Directory `
                | Where-Object { $_.Name -match '\d+(\.\d+)*' } `
                | Select -ExpandProperty "FullName" -First 1
            }
            If ($VersionPath -ne $null) {
                # Create DeinstallPath array
                $DeinstallPath = @()
                # Get each instance of "deinstall" subdirectory from each VersionPath
                $VersionPath | ForEach-Object {
                    $DeinstallPath += Get-ChildItem -Path $_ -Recurse -Directory `
                    | Where-Object { $_.Name -eq 'deinstall' -and $_.FullName -notlike "*\inventory\*"} `
                    | Select -ExpandProperty "FullName" -First 1
                }
                If ($DeinstallPath -ne $null) {
                    # Create DeinstallBatch array
                    $DeinstallBatch = @()
                    # Get each instance of "deinstall.bat" file from each DeinstallPath
                    $DeinstallPath | ForEach-Object {
                        $DeinstallBatch += Get-ChildItem -Path $_ -File `
                        | Where-Object { $_.Name -eq 'deinstall.bat'} `
                        | Select -ExpandProperty "FullName" -First 1
                     }
                     If ($DeinstallBatch -ne $null) {
                         # Create temporary directory
                         If (!(Test-Path $TempDir)) {
                             New-Item -Path "$TempDir" -ItemType Directory -Force
                         }
                         $DeinstallBatch | ForEach-Object {
                             # Create array for parent-most directories (for later removal)
                             $DriveLetter = Split-Path -Path $_ -Qualifier
                             $ParentDir = (Split-Path -Path $_ -Parent).Split('\', [System.StringSplitOptions]::RemoveEmptyEntries)[1]
                             $ParentDirs = @()
                             $ParentDirs += Join-Path $DriveLetter $ParentDir
                             # Get version number from file path
                             $VersionNumber = [regex]::Match($_, "\\(\d+(\.\d+)+)\\").Groups[1].Value
                             # Append version number to TempDir for appropriate naming of subdirectory
                             $TempSubDir = Join-Path $TempDir $VersionNumber
                             # Create temporary subdirectory
                             If (!(Test-Path $TempSubDir)) {
                                 New-Item -Path "$TempSubDir" -ItemType Directory -Force
                             }
                             # Create .RSP file in subdirectory using deinstall.bat
                             Start-Process -FilePath "$_" -Wait -NoNewWindow -ArgumentList "-silent -checkonly -o $TempSubDir"
                             # Execute deinstall.bat using .RSP file
                             $RSP = Join-Path $TempSubDir '\deinstall*.rsp'
                             Start-Process -FilePath "$_" -Wait -NoNewWindow -ArgumentList "-silent -paramfile $RSP"
                        }
                    }
                }
            }
        }
        # Remove parent-most directories for all Oracle instances
        If ($ParentDirs -ne $null) {
            Remove-Item -Path $ParentDirs -Force -Recurse -ErrorAction SilentlyContinue
        }
        # Remove temporary directory
        If (Test-Path $TempDir) {
            Remove-Item -Path $TempDir -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 Uninstall-Oracle Function

# Set-EnvironmentVariable Function
Function Set-EnvironmentVariable {
    param (
        $Name,
        $Value
    )
    [System.Environment]::SetEnvironmentVariable($Name,$Value,[System.EnvironmentVariableTarget]::Machine)
    [System.Environment]::SetEnvironmentVariable($Name,$Value,[System.EnvironmentVariableTarget]::User)
    [System.Environment]::SetEnvironmentVariable($Name,$Value,[System.EnvironmentVariableTarget]::Process)
} # End of Set-EnvironmentVariable Function

# Update-EnvironmentVariables Function
Function Update-EnvironmentVariables {
    # 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 Update-EnvironmentVariables Function
 
# Remove-RegistryKey Function
Function Remove-RegistryKey {
    param (
        $Key
    )
    Remove-Item -Path "Registry::$Key" -Force -Recurse
} # End of Remove-RegistryKey Function
 
# Call Uninstall-Oracle function
Uninstall-Oracle -TargetDrive $TargetDrive -ExcludeDirs $ExcludeDirs -TempDir $TempDir
 
# Nullify environment variables
Set-EnvironmentVariable -Name "TNS_Admin"     -Value "$null"
Set-EnvironmentVariable -Name "_JAVA_OPTIONS" -Value "$null"
Set-EnvironmentVariable -Name "ORACLE_HOME"   -Value "$null"
 
# Refresh environment variables
Update-EnvironmentVariables
 
# Remove Registry Keys
Remove-RegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Oracle*"
Remove-RegistryKey -Key "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Oracle*"
Remove-RegistryKey -Key "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Oracle*"

4 thoughts on “PowerShell- UltimateOCD Update + Demo”

  1. Juzer says:
    July 19, 2023 at 8:54 pm

    Hi Payton,

    I tried your modified script. It performs partial removal; it does not delete all files and folders.

    Thanks.

    Reply
    1. paytonflint says:
      July 20, 2023 at 1:21 am

      Can you elaborate on what was left behind?

      Reply
      1. Juzer says:
        August 10, 2023 at 12:02 am

        Hi Payton,
        There were at least three folders that were not erased. Those folders have to be deleted manually. Also, I would like you to provide a functionality that checks whether or not Oracle is present on the server. If it is not there, the program should exit with the message “Oracle not found.”

        Truly appreciate your efforts.

        Thank you.

        Reply
  2. Juzer says:
    August 29, 2023 at 3:29 pm

    Hi Payton,

    Please reply to my above message. Whether it is possible to do that or not. Thanks.

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

About The Author

Author's Portrait

In my journey as a technologist and 11 years of experience as an IT professional, I have found my niche as Director of Infrastructure Services; developing my skillsets in management, scripting, cloud infrastructure, identity management, and networking.

I have experience as a Systems Administrator and Engineer for large enterprises including the DoD, government agencies, and a nuclear-generation site.

I've been blessed to collaborate with engineers at esteemed Fortune 50 corporations, and one of Africa's largest, to ensure successful implementation of my work.

GitHub Button

Credentials

M365 Endpoint Administrator Associate
M365 Fundamentals
Microsoft AZ-900
CompTIA CSIS
CompTIA CIOS
CompTIA Security+
CompTIA Network+
CompTIA A+
  • April 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
© 2022 Payton Flint | The views and opinions expressed on this website belong solely to the author/owner and do not represent the perspectives of any individuals, institutions, or organizations, whether affiliated personally or professionally, unless explicitly stated otherwise. The content and products on this website are provided as-is with no warranties or guaranties, are for informational/demonstrative purposes only, do not constitute professional advice, and are not to be used maliciously. The author/owner is not responsible for any consequences arising from actions taken based on information provided on this website, nor from the use/misuse of products from this site. All trademarks are the property of their respective owners.