Worklet: Uninstall RingCentral Phone or Other Software Installed In User Space

RingCentral Phone gets installed in the user space, not in Program Files:
C:\Users[username]\AppData\Local\RingCentral

So you can’t uninstall it with a typical uninstall worklet because it’s running as the SYSTEM user. This worklet uses the task scheduler to create the uninstall tasks, do the uninstall, and then delete the tasks.

Be sure to set $appName to the name of the app you want uninstalled in both evaluation and remediation code.

<#
.SYNOPSIS
  Check for presence of specified application on the target device

.DESCRIPTION
  Read 32-bit and 64-bit registry to find matching applications

  Exits with 0 for compliance, 1 for Non-Compliance. 
  Non-Compliant devices will run Remediation Code at the Policy's next scheduled date.

.NOTES
  A scriptblock is used to workaround the limitations of 32-bit powershell.exe.
  This allows us to redirect the operations to a 64-bit powershell.exe and read
  the 64-bit registry without .NET workarounds.

.LINK
http://www.automox.com
#>

# The ScriptBlock method used here is to allow a 32-bit agent process
# to access the 64-bit registry on 64-bit Windows. This is necessary if the application
# isn't known to be 32-bit only.

$scriptblock = {
    #Define Registry Location for the 64-bit and 32-bit Uninstall keys
    $uninstReg = @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall','HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')

    # Define the App Name to look for
    # Look at a machine with the application installed unless you're sure the formatting of the name/version
    # Specifically the DisplayName. This is what you see in Add/Remove Programs. This doesn't have to be exact.
    # Default behavior uses -match which is essentially "DisplayName contains VLC"
    ##################
    $appName = 'RingCentral'
    ##################

    # Get all entries that match our criteria. DisplayName matches $appname
    $installed = @(Get-ChildItem $uninstReg -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object { ($_.DisplayName -match $appName) })

    # If any matches were present, $installed will be populated. If none, then $installed is NULL and this IF statement will be false.
    # The return value here is what the ScriptBlock will send back to us after we run it.
    # 1 for Non-Compliant, 0 for Compliant
    if ($installed) {
        return 1
    } else { return 0 }
}

$exitCode = & "$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -NonInteractive -Command $scriptblock
Exit $exitCode

Remediation:

$scriptblock = {

    #Define Registry Location for Uninstall keys
    $uninstReg = @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall','HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')

    # Look at a machine with the application installed unless you're sure the formatting of the name/version
    ##################
    $appName = 'RingCentral'
    ##################

    # Get all entries that match our criteria. DisplayName matches $appname, DisplayVersion less than current
    $installed = @(Get-ChildItem $uninstReg -ErrorAction SilentlyContinue | Get-ItemProperty | Where-Object { ($_.DisplayName -match $appName) })
    
    #Get User details including SID from Get-LocalUser
    $users = Get-CimInstance -Class Win32_UserProfile -Filter "Special = $false"

    # Start a loop in-case you get more than one match, uninstall each.
    foreach ($version in $installed) {
        #For every version found, run the uninstall string
        $uninstString = $version.UninstallString

        #If exe run as written + silent argument, if msiexec run as msi using the name of the reg key as the msi guid.
        if ($uninstString -match 'msiexec') {

            $execute = "msiexec.exe"
            $arg = "/x $($version.PSChildName) /qn /norestart"

        } else {

            $execute = """$uninstString"""
            $arg = "/s"

        }

        # Create, run, then delete the uninstall scheduled task
        $time = (Get-Date).AddSeconds(30)
        $triggerAt = New-ScheduledTaskTrigger -At $time -Once
        $action = New-ScheduledTaskAction -Execute $execute -Argument $arg
        $currentusr = (Get-WmiObject -class win32_process -ComputerName 'localhost' | Where-Object name -Match explorer).getowner().user

        Register-ScheduledTask -TaskName "Uninstall $appName" -Trigger $triggerAt -Action $action -User $currentusr
        Start-Sleep 31
        Unregister-ScheduledTask -TaskName "Uninstall $appName" -Confirm:$false
        
    }
}

$uninstalledApps = & "$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -NonInteractive -Command $scriptblock

# Use Write-Output so you can see a result in the Activity Log
Write-Output "$uninstalledApps"
1 Like