Problems executing actions on users - PowerShell

Hello everyone,

I’m having difficulties creating a PowerShell script. The goal of this script is to remove a program.

Basically, I’ve created several scripts for removing other programs, and these scripts work perfectly. All test runs through BigFix were successful. Below is one of the successful scripts:

function UninstallProgram {
  param(
    [string]$programName
  )

  function Stop-Process {
    $process = Get-Process | Where-Object { $_.ProcessName -eq "ultravnc" }
    if ($process) {
        Write-Host "Process found. Process ID: $($process.Id)"
        Stop-Process -Id $process.Id -Force
        Write-Host "Process stopped successfully."
    } else {
        Write-Host "Process not found."
    }
  }

  Stop-Process

  $registryKeys = @(
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
    "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
  )

  foreach ($registryKey in $registryKeys) {

    if ($registryKey.StartsWith("HKU:")) {
      $sid = $registryKey -replace "HKU:\\"
      $userReg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', '') 
      $regKey = $userReg.OpenSubKey("$sid\Software\Microsoft\Windows\CurrentVersion\Uninstall")
      if ($regKey -eq $null) {
        continue
      }
      $uninstallKeys = $regKey.GetSubKeyNames() | ForEach-Object { $regKey.OpenSubKey($_) }
    } else {
      $uninstallKeys = Get-ChildItem $registryKey | Get-ItemProperty
    }

    foreach ($key in $uninstallKeys) {
      if ($key.DisplayName -match $programName) {
        $uninstallString = $key.UninstallString

        $is64BitApp = $uninstallString -match "SysWOW64"

        if ($uninstallString -notlike "*  /VERYSILENT") {
          $uninstallString += " /VERYSILENT"
        }

        Write-Host "UninstallString value: $uninstallString"

        Write-Host "Uninstalling $($key.DisplayName) silently..."
        Start-Process -FilePath "cmd.exe" -ArgumentList "/c $uninstallString" -WindowStyle Hidden -PassThru -Wait
        Write-Host "$($key.DisplayName) uninstalled successfully."
        return
      }
    }
  }

  Write-Host "$programName not found. No action taken."
}

UninstallProgram "UltraVNC"

In this script above, the UninstallString is looked up during execution. I also tried to do it this way for the other script I’m creating, but it hasn’t been working.

The difference between the UltraVNC program and dotPeek is that the uninstallstring for UltraVNC is located in HKEY_LOCAL_MACHINE, while for dotPeek it is located in HKEY_USERS. The application itself is installed only for the user.

Whenever I try to make any changes related to users through BigFix, some kind of problem occurs. Is it possible that the problem is with permissions? Doesn’t BigFix already run as Administrator?

Also, I would like to share below the newly created PowerShell script for dotPeek removal. The script works in the PowerShell ISE tool, but not when executed by BigFix. It is also worth noting that I wanted to make this script as simple as possible, already with the uninstallstring provided so that there are no conflicts with environment variables when it comes to users (if that is a possibility).

function UninstallDotPeek {
    Start-Process -FilePath "cmd.exe" -ArgumentList '/c "C:\Users\user_123\AppData\Local\JetBrains\Installations\dotPeek233\JetBrains.Platform.Installer.exe" /HostsToRemove=dotPeek233 /sile' -WindowStyle Hidden -PassThru -Wait
    return $true
}

UninstallDotPeek

Does anyone have any idea what it could be?

It’s not a matter of permissions, it’s a matter of environment. Try it yourself, outside of BigFix.
Set up two user accounts, “Administrator” and “User1”. If you perform a per-user install of ‘dotPeek’, as User1, you should not see that in Add/Remove Programs or your PowerShell script when you run as Administrator. If you looked up the actual uninstall command and executed it, it likely still would not work as expected because the uninstaller is referencing values under HKEY_CURRENT_USER – and the definition of HKEY_CURRENT_USER for ‘User1’ is different than the mount of HKEY_CURRENT_USER for the user ‘Administrator’.

There are several approaches you can take; none of them particularly easy.

  1. You can invest in MDM. BigFix provides a pretty nice one, but you do have to deal with enrolling your users/machines. With MDM policy you can take control of user environment setup.

  2. You could check out the thread updated yesterday at Thread execution failed - #17 by JasonWalker about using the ‘override’ commands to execute processes like this uninstall in the logged-on user context. You’ll need to craft Relevance so the task is only relevant when there is a logged-on user, and that user has the registry key or file in their profile to indicate the thing is installed; and configure the Action Settings to either ‘reapply while relevant’ or ‘reapply whenever it becomes relevant again’ so that the uninstall is repeated the next time a user with the per-user-install logs on.

  3. You could craft the uninstall as a Logon Script so that every time a user logs on, your PowerShell executes, checks whether the thing is installed, and uninstalls it. The Logon Script runs as the current user, so that should take care of the user-context.

  4. You could configure an ActiveSetup script, which is very similar to the Logon Script, except that it only runs one time for each user the next time they log on; if they reinstall the product again after you remove it, ActiveSetup won’t run repeatedly to get rid of it again. This is a very little-documented area of Windows but I do have some discussion and examples posted at Delete Multiple Office Profiles in Registry Keys Under HKEY_Users - #5 by JasonWalker

If anyone else has options for managing per-user installs I’d love to hear them, but I think this is a pretty good overview of the options as I know them today.

1 Like