Microsoft Teams craptacular Machine-Wide Installer

I’m hoping someone might be able to help me with a problem I’ve facing…

About a year ago I deployed the Microsoft Teams Machine-Wide Installer (MSI) via the PSADT in the User context. The MSI was crap, and this was the only way to accomplish the installation properly. Teams is a user-based install and Microsoft hacked together a Machine-Wide installer which, as far as I know, just launches the MSI installer each time a new user logs in… It’s not ideal. Long story short, I forgot all about this and recently deployed an updated version of the MSI, but this time as System. And then the fun started…

My first mistake was marking the deployment as Required, because it then automatically ran on a couple dozen machines. Two entries for the Teams Machine-Wide Installer are now present in HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall. I assume there’s a MSI Code for the old install {DF8C4194-1791-41CC-A455-8EBCCF084366}, and one for the new install {731F6BAA-A986-45A4-8936-7C3AAAAA760B}. And for whatever reason, some machines are stuck in a loop where the Detection Logic for {731F6BAA-A986-45A4-8936-7C3AAAAA760B} just simply isn’t working even though it’s clearly valid.

So, I decided to purge the applicaiton in Configuration Manager and create a new one using PSADT to simply purge everything, re-install the Teams Machine-Wide Installer, and then reboot. Here’s the installation code I’m using:

		##*===============================================
	##* PRE-INSTALLATION
	##*===============================================
	[string]$installPhase = 'Pre-Installation'
	
	
	# CLEAN OLD TEAMS INSTALLS
    Show-InstallationProgress -StatusMessage "Searching for previous Teams installations. Please wait..."
	$TeamsPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, 'Microsoft', 'Teams')
	$TeamsUpdateExePath = [System.IO.Path]::Combine($env:LOCALAPPDATA, 'Microsoft', 'Teams', 'Update.exe')
	if (Test-Path -Path $TeamsUpdateExePath) {
		Show-InstallationProgress -StatusMessage "Uninstalling previous Teams installation. Please wait..."
		$proc = Start-Process -FilePath $TeamsUpdateExePath -ArgumentList "-uninstall -s" -PassThru
		$proc.WaitForExit()
	}
	if (Test-Path -Path $TeamsPath) {
		Show-InstallationProgress -StatusMessage "Cleaning previous Teams installation. Please wait..."
		Remove-Item –Path $TeamsPath -Recurse
	}
    Start-Sleep -Seconds 10
	$Paths = Get-UserProfiles | Select-Object -ExpandProperty 'ProfilePath'
	foreach ($Path in $Paths)
	{
		Remove-Folder -Path "$path\AppData\Local\Microsoft\Teams" -ContinueOnError $true
	}
	Remove-MSIApplications -Name 'Teams Machine-Wide Installer'
    Remove-MSIApplications -Name 'Teams Machine-Wide Installer'
    Remove-MSIApplications -Name 'Microsoft Teams'
    Execute-MSI -Action 'Uninstall' -Path '{731F6BAA-A986-45A4-8936-7C3AAAAA760B}'
    Execute-MSI -Action 'Uninstall' -Path '{DF8C4194-1791-41CC-A455-8EBCCF084366}'
    Remove-Folder -Path "${env:ProgramFiles(x86)}\Teams Installer"
	# /CLEAN OLD TEAMS INSTALLS

	
	##*===============================================
	##* INSTALLATION 
	##*===============================================
	[string]$installPhase = 'Installation'
	
	Show-InstallationProgress -StatusMessage "Installing Microsoft Teams. Please wait..."
	Execute-MSI -Action 'Install' -Path 'Teams_windows_x64.msi' -PassThru

As you can see, I’m trying numerous things to remove the installer… The problem is, the MSI files are not always removed. I’m guessing this is because Remove-MSIApplications is running as System, and the original MSI was installed as User? If that’s the case, is there a way to remove an MSI as User while keeping the Deployment Type running as System? Or maybe I could switch the DeploymentType to User, and then when the script reaches the Execute-MSI cmdlet I could run this as System? Is that even possible?

Any help would be greatly appreciated. Thank you so much.

To help someone else in this situation, using the Execute-ProcessAsUser allowed me to uninstall the MSI’s which were originally installed in the User context, but only if the same user was currently logged in… I have not been able to determine if there’s a method to uninstall an MSI across all users.

Execute-ProcessAsUser -Path "$($envWinDir)\System32\msiexec.exe" -Parameters "/x {731F6BAA-A986-45A4-8936-7C3AAAAA760B} /qn" -RunLevel HighestAvailable -Wait -PassThru
Execute-ProcessAsUser -Path "$($envWinDir)\System32\msiexec.exe" -Parameters "/x {DF8C4194-1791-41CC-A455-8EBCCF084366} /qn" -RunLevel HighestAvailable -Wait -PassThru

Found a way to use this clean up script with some other triggers to avoid the scenario where traces of Teams still exist in registry preventing Teams from launching. Added the following into my O365 PS ADT script:

##===============================================
##
POST-INSTALLATION
##*===============================================
[string]$installPhase = ‘Post-Installation’

CLEAN OLD TEAMS INSTALLS

Show-InstallationProgress -StatusMessage "Searching for previous Teams installations. Please wait..."

$TeamsPath = [System.IO.Path]::Combine($env:LOCALAPPDATA, ‘Microsoft’, ‘Teams’)
$TeamsUpdateExePath = [System.IO.Path]::Combine($env:LOCALAPPDATA, ‘Microsoft’, ‘Teams’, ‘Update.exe’)
if (Test-Path -Path $TeamsUpdateExePath) {
Show-InstallationProgress -StatusMessage “Uninstalling previous Teams installation. Please wait…”
$proc = Start-Process -FilePath $TeamsUpdateExePath -ArgumentList “-uninstall -s” -PassThru
$proc.WaitForExit()
}
if (Test-Path -Path $TeamsPath) {
Show-InstallationProgress -StatusMessage “Cleaning previous Teams installation. Please wait…”
Remove-Item –Path $TeamsPath -Recurse
}
Start-Sleep -Seconds 10
$Paths = Get-UserProfiles | Select-Object -ExpandProperty ‘ProfilePath’
foreach ($Path in $Paths)
{
Remove-Folder -Path “$path\AppData\Local\Microsoft\Teams” -ContinueOnError true } Remove-MSIApplications -Name 'Teams Machine-Wide Installer' Remove-MSIApplications -Name 'Teams Machine-Wide Installer' Remove-MSIApplications -Name 'Microsoft Teams' Execute-MSI -Action 'Uninstall' -Path '{731F6BAA-A986-45A4-8936-7C3AAAAA760B}' Execute-MSI -Action 'Uninstall' -Path '{DF8C4194-1791-41CC-A455-8EBCCF084366}' Remove-Folder -Path "{env:ProgramFiles(x86)}\Teams Installer"

/CLEAN OLD TEAMS INSTALLS

  ##*===============================================
  ##* INSTALLATION 
  ##*===============================================
  [string]$installPhase = 'Installation'
  
  ## Handle Zero-Config MSI Installations
  If ($useDefaultMsi) {
  	[hashtable]$ExecuteDefaultMSISplat =  @{ Action = 'Install'; Path = $defaultMsiFile }; If ($defaultMstFile) { $ExecuteDefaultMSISplat.Add('Transform', $defaultMstFile) }
  	Execute-MSI @ExecuteDefaultMSISplat; If ($defaultMspFiles) { $defaultMspFiles | ForEach-Object { Execute-MSI -Action 'Patch' -Path $_ } }
  }
  
  ## <Perform Installation tasks here>
  
  Execute-MSI -Action 'Install' -path 'Teams_windows_x64.msi' -Parameters 'OPTIONS="noAutoStart=true" /passive ALLUSERS=1 REBOOT=ReallySuppress'

    Start-Process -FilePath "teams.exe" -WorkingDirectory "C:\Program Files (x86)\Teams Installer"

The remove-folder is not a valid powershell command. The correct command should be like this:
Remove-Item -Path “$path\AppData\Local\Microsoft\Teams” -ErrorAction SilentlyContinue}
Make note that you can go a step or two further and tell powershell it is a directory with a -Directory and the error action is also not correct. Use this line in it’s place and drop this into the PSAppDeploy script in the Pre-Installation making sure to comment our the Clean and /Clean lines. This will work and I wrote a similar script to this.

Remove-Folder isn’t a powershell command but it’s a toolkit command. Basically a wrapper for remove-item.