diff --git a/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_install.ps1 b/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_install.ps1 new file mode 100644 index 0000000000..877009684d --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_install.ps1 @@ -0,0 +1,29 @@ +# Learn more about .exe install scripts: +# http://fleetdm.com/learn-more-about/exe-install-scripts + +$exeFilePath = "${env:INSTALLER_PATH}" + +try { + +# TeamViewer Host ships as an NSIS installer, which takes "/S" for a silent +# install. The MSI underneath sets ALLUSERS=1, so this always installs +# machine-wide. +$processOptions = @{ + FilePath = "$exeFilePath" + ArgumentList = "/S" + PassThru = $true + Wait = $true +} + +# Start process and track exit code +$process = Start-Process @processOptions +$exitCode = $process.ExitCode + +# Prints the exit code +Write-Host "Install exit code: $exitCode" +Exit $exitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_uninstall.ps1 b/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_uninstall.ps1 new file mode 100644 index 0000000000..9ff2a4a7ca --- /dev/null +++ b/ee/maintained-apps/inputs/winget/scripts/teamviewer-host_uninstall.ps1 @@ -0,0 +1,95 @@ +# TeamViewer Host registers itself in Add/Remove Programs with the DisplayName +# "TeamViewer Host" (the MSI ProductName; there is no ARPDISPLAYNAME override) +# and the Publisher "TeamViewer" (the MSI Manufacturer). +# +# The trailing wildcard tolerates a version suffix if TeamViewer ever adds one, +# and the "Host" in the pattern keeps this from matching the full TeamViewer +# client, which registers as plain "TeamViewer" and ships as its own +# Fleet-maintained app (teamviewer/windows). +$softwareNameLike = "TeamViewer Host*" + +# Matched with a trailing wildcard so this filter stays strictly looser than the +# app's exists query (publisher = 'TeamViewer'). Uninstall must never be more +# selective than detection, or the app reports installed with no way to remove it. +$publisherLike = "TeamViewer*" + +$paths = @( + 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', + 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' +) + +try { + +$uninstall = $null +foreach ($p in $paths) { + $items = Get-ItemProperty "$p\*" -ErrorAction SilentlyContinue | Where-Object { + $_.DisplayName -like $softwareNameLike -and $_.Publisher -like $publisherLike + } + if ($items) { $uninstall = $items | Select-Object -First 1; break } +} + +if (-not $uninstall) { + Write-Host "Uninstall entry not found for $softwareNameLike" + Exit 0 +} + +if (-not $uninstall.UninstallString -and -not $uninstall.QuietUninstallString) { + Write-Host "Error: uninstall entry for $($uninstall.DisplayName) has no UninstallString or QuietUninstallString" + Exit 1 +} + +# Get the uninstall command. Some uninstallers do not include +# 'QuietUninstallString' and require a flag to run silently. +$uninstallCommand = if ($uninstall.QuietUninstallString) { + $uninstall.QuietUninstallString +} else { + $uninstall.UninstallString +} + +# UninstallString comes in three shapes. TeamViewer's is unquoted and +# contains a space ("C:\Program Files\TeamViewer\uninstall.exe"), so +# capture through the .exe rather than splitting on the first space. +$existingArgs = '' +if ($uninstallCommand -match '^\s*"([^"]+)"\s*(.*)$') { + # Quoted path, optionally followed by args + $uninstallCommand = $Matches[1] + $existingArgs = $Matches[2].Trim() +} elseif ($uninstallCommand -match '(?i)^\s*(.+?\.exe)\s*(.*)$') { + # Unquoted path that may contain spaces + $uninstallCommand = $Matches[1] + $existingArgs = $Matches[2].Trim() +} elseif ($uninstallCommand -match '^\s*(\S+)\s*(.*)$') { + # Bare token (e.g. MsiExec.exe /X{GUID}) + $uninstallCommand = $Matches[1] + $existingArgs = $Matches[2].Trim() +} else { + Throw "Could not parse uninstall string: $uninstallCommand" +} + +# NSIS installers require /S for a silent uninstall. Append it unless the +# registered command already runs silently. +if ($existingArgs -notmatch '(?i)(^|\s)/S(\s|$)') { + $uninstallArgs = "$existingArgs /S".Trim() +} else { + $uninstallArgs = $existingArgs +} + +Write-Host "Uninstall command: $uninstallCommand" +Write-Host "Uninstall args: $uninstallArgs" + +$processOptions = @{ + FilePath = $uninstallCommand + ArgumentList = $uninstallArgs + PassThru = $true + Wait = $true +} + +$process = Start-Process @processOptions +$exitCode = $process.ExitCode +Write-Host "Uninstall exit code: $exitCode" +Exit $exitCode + +} catch { + Write-Host "Error: $_" + Exit 1 +} diff --git a/ee/maintained-apps/inputs/winget/teamviewer-host.json b/ee/maintained-apps/inputs/winget/teamviewer-host.json new file mode 100644 index 0000000000..04fc788fdc --- /dev/null +++ b/ee/maintained-apps/inputs/winget/teamviewer-host.json @@ -0,0 +1,15 @@ +{ + "name": "TeamViewer Host", + "slug": "teamviewer-host/windows", + "package_identifier": "TeamViewer.TeamViewer.Host", + "unique_identifier": "TeamViewer Host", + "install_script_path": "ee/maintained-apps/inputs/winget/scripts/teamviewer-host_install.ps1", + "uninstall_script_path": "ee/maintained-apps/inputs/winget/scripts/teamviewer-host_uninstall.ps1", + "installer_arch": "x64", + "installer_type": "exe", + "installer_scope": "machine", + "ignore_hash": true, + "default_categories": [ + "Communication" + ] +} diff --git a/ee/maintained-apps/outputs/apps.json b/ee/maintained-apps/outputs/apps.json index 610fa62cd9..74a8bac058 100644 --- a/ee/maintained-apps/outputs/apps.json +++ b/ee/maintained-apps/outputs/apps.json @@ -8436,6 +8436,13 @@ "unique_identifier": "com.apptorium.TeaCode-dm", "description": "TeaCode is a text expanding app for developers." }, + { + "name": "TeamViewer Host", + "slug": "teamviewer-host/windows", + "platform": "windows", + "unique_identifier": "TeamViewer Host", + "description": "TeamViewer Host is a remote access agent for unattended 24/7 access to a device, for uses such as remote device monitoring and server maintenance." + }, { "name": "TeamViewer", "slug": "teamviewer/darwin", diff --git a/ee/maintained-apps/outputs/teamviewer-host/windows.json b/ee/maintained-apps/outputs/teamviewer-host/windows.json new file mode 100644 index 0000000000..c0617fe8c3 --- /dev/null +++ b/ee/maintained-apps/outputs/teamviewer-host/windows.json @@ -0,0 +1,22 @@ +{ + "versions": [ + { + "version": "15.80.4", + "queries": { + "exists": "SELECT 1 FROM programs WHERE name = 'TeamViewer Host' AND publisher = 'TeamViewer';", + "patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM programs WHERE name = 'TeamViewer Host' AND publisher = 'TeamViewer' AND version_compare(version, '15.80.4') < 0);" + }, + "installer_url": "https://download.teamviewer.com/download/version_15x/TeamViewer_Host_Setup_x64.exe", + "install_script_ref": "0c887797", + "uninstall_script_ref": "6e2af20a", + "sha256": "no_check", + "default_categories": [ + "Communication" + ] + } + ], + "refs": { + "0c887797": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\ntry {\n\n# TeamViewer Host ships as an NSIS installer, which takes \"/S\" for a silent\n# install. The MSI underneath sets ALLUSERS=1, so this always installs\n# machine-wide.\n$processOptions = @{\n FilePath = \"$exeFilePath\"\n ArgumentList = \"/S\"\n PassThru = $true\n Wait = $true\n}\n\n# Start process and track exit code\n$process = Start-Process @processOptions\n$exitCode = $process.ExitCode\n\n# Prints the exit code\nWrite-Host \"Install exit code: $exitCode\"\nExit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n", + "6e2af20a": "# TeamViewer Host registers itself in Add/Remove Programs with the DisplayName\n# \"TeamViewer Host\" (the MSI ProductName; there is no ARPDISPLAYNAME override)\n# and the Publisher \"TeamViewer\" (the MSI Manufacturer).\n#\n# The trailing wildcard tolerates a version suffix if TeamViewer ever adds one,\n# and the \"Host\" in the pattern keeps this from matching the full TeamViewer\n# client, which registers as plain \"TeamViewer\" and ships as its own\n# Fleet-maintained app (teamviewer/windows).\n$softwareNameLike = \"TeamViewer Host*\"\n\n# Matched with a trailing wildcard so this filter stays strictly looser than the\n# app's exists query (publisher = 'TeamViewer'). Uninstall must never be more\n# selective than detection, or the app reports installed with no way to remove it.\n$publisherLike = \"TeamViewer*\"\n\n$paths = @(\n 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall',\n 'HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall'\n)\n\ntry {\n\n$uninstall = $null\nforeach ($p in $paths) {\n $items = Get-ItemProperty \"$p\\*\" -ErrorAction SilentlyContinue | Where-Object {\n $_.DisplayName -like $softwareNameLike -and $_.Publisher -like $publisherLike\n }\n if ($items) { $uninstall = $items | Select-Object -First 1; break }\n}\n\nif (-not $uninstall) {\n Write-Host \"Uninstall entry not found for $softwareNameLike\"\n Exit 0\n}\n\nif (-not $uninstall.UninstallString -and -not $uninstall.QuietUninstallString) {\n Write-Host \"Error: uninstall entry for $($uninstall.DisplayName) has no UninstallString or QuietUninstallString\"\n Exit 1\n}\n\n# Get the uninstall command. Some uninstallers do not include\n# 'QuietUninstallString' and require a flag to run silently.\n$uninstallCommand = if ($uninstall.QuietUninstallString) {\n $uninstall.QuietUninstallString\n} else {\n $uninstall.UninstallString\n}\n\n# UninstallString comes in three shapes. TeamViewer's is unquoted and\n# contains a space (\"C:\\Program Files\\TeamViewer\\uninstall.exe\"), so\n# capture through the .exe rather than splitting on the first space.\n$existingArgs = ''\nif ($uninstallCommand -match '^\\s*\"([^\"]+)\"\\s*(.*)$') {\n # Quoted path, optionally followed by args\n $uninstallCommand = $Matches[1]\n $existingArgs = $Matches[2].Trim()\n} elseif ($uninstallCommand -match '(?i)^\\s*(.+?\\.exe)\\s*(.*)$') {\n # Unquoted path that may contain spaces\n $uninstallCommand = $Matches[1]\n $existingArgs = $Matches[2].Trim()\n} elseif ($uninstallCommand -match '^\\s*(\\S+)\\s*(.*)$') {\n # Bare token (e.g. MsiExec.exe /X{GUID})\n $uninstallCommand = $Matches[1]\n $existingArgs = $Matches[2].Trim()\n} else {\n Throw \"Could not parse uninstall string: $uninstallCommand\"\n}\n\n# NSIS installers require /S for a silent uninstall. Append it unless the\n# registered command already runs silently.\nif ($existingArgs -notmatch '(?i)(^|\\s)/S(\\s|$)') {\n $uninstallArgs = \"$existingArgs /S\".Trim()\n} else {\n $uninstallArgs = $existingArgs\n}\n\nWrite-Host \"Uninstall command: $uninstallCommand\"\nWrite-Host \"Uninstall args: $uninstallArgs\"\n\n$processOptions = @{\n FilePath = $uninstallCommand\n ArgumentList = $uninstallArgs\n PassThru = $true\n Wait = $true\n}\n\n$process = Start-Process @processOptions\n$exitCode = $process.ExitCode\nWrite-Host \"Uninstall exit code: $exitCode\"\nExit $exitCode\n\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n" + } +} diff --git a/website/assets/images/app-icon-teamviewer-host-60x60@2x.png b/website/assets/images/app-icon-teamviewer-host-60x60@2x.png new file mode 100644 index 0000000000..298113cfb1 Binary files /dev/null and b/website/assets/images/app-icon-teamviewer-host-60x60@2x.png differ