Skip to content

Commit bc30cf3

Browse files
added new Get-TeamViewerInstallationTypefunction that returns the installation type of TeamViewer (MSI, Exe, or Unknown)
1 parent 9fea298 commit bc30cf3

4 files changed

Lines changed: 356 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
function Get-TeamViewerInstallationType {
2+
3+
[CmdletBinding()]
4+
[OutputType([string])]
5+
param()
6+
7+
$regPath = 'HKLM:\SOFTWARE\TeamViewer'
8+
$regPathWow = 'HKLM:\SOFTWARE\WOW6432Node\TeamViewer'
9+
$msiDatabaseFound = $false
10+
$msiRegistryValueFound = $false
11+
12+
#first check Msi database
13+
try {
14+
$msiProduct = Get-CimInstance -ClassName Win32_Product -Filter "Name='TeamViewer'" -ErrorAction Stop
15+
if ($msiProduct) {
16+
$msiDatabaseFound = $true
17+
}
18+
}
19+
catch {
20+
Write-Verbose "Msi database check failed or TeamViewer not found via WMI"
21+
}
22+
23+
#check MsiInstallation value
24+
foreach ($path in @($regPath, $regPathWow)) {
25+
try {
26+
$msiInstallationValue = Get-ItemProperty -Path $path -Name 'MsiInstallation' -ErrorAction Stop
27+
28+
if ($null -ne $msiInstallationValue.MsiInstallation -and $msiInstallationValue.MsiInstallation -eq 1) {
29+
$msiRegistryValueFound = $true
30+
break
31+
}
32+
}
33+
catch [System.Management.Automation.ItemNotFoundException] {
34+
Write-Verbose "TeamViewer registry path not found: $path"
35+
}
36+
catch {
37+
Write-Verbose "registry check for MsiInstallation failed at $path"
38+
}
39+
}
40+
41+
if ($msiDatabaseFound -and $msiRegistryValueFound) {
42+
return 'Msi'
43+
}
44+
45+
#check for ExeInstallation
46+
try {
47+
$uninstallPaths = @(
48+
'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall',
49+
'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
50+
)
51+
52+
foreach ($uninstallPath in $uninstallPaths) {
53+
if (Test-Path -Path $uninstallPath) {
54+
$teamViewerKey = Get-ChildItem -Path $uninstallPath -ErrorAction SilentlyContinue |
55+
Where-Object { $_.GetValue('DisplayName') -like '*TeamViewer*' }
56+
57+
if ($teamViewerKey) {
58+
$uninstallValue = Get-ItemProperty -Path $teamViewerKey.PSPath -Name 'UninstallString' -ErrorAction SilentlyContinue
59+
60+
if ($uninstallValue -and $uninstallValue.UninstallString) {
61+
#extract the executable path using regex
62+
$uninstallFile = $uninstallValue.UninstallString -replace '^"?([^"]+)"?.*$', '$1'
63+
$uninstallFile = $uninstallFile.Trim('"')
64+
#verify if it's a file and if it exists
65+
if (Test-Path -Path $uninstallFile -PathType Leaf) {
66+
return 'Exe'
67+
}
68+
else {
69+
return 'Unknown'
70+
}
71+
}
72+
}
73+
}
74+
}
75+
}
76+
catch {
77+
Write-Verbose "Error checking UninstallString"
78+
}
79+
80+
return 'Unknown'
81+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
external help file: TeamViewerPS-help.xml
3+
Module Name: TeamViewerPS
4+
online version: https://github.com/teamviewer/TeamViewerPS/blob/main/Docs/Help/Get-TeamViewerInstallationType.md
5+
schema: 2.0.0
6+
---
7+
8+
# Get-TeamViewerInstallationType
9+
10+
## SYNOPSIS
11+
12+
Returns the TeamViewer installation type.
13+
14+
## SYNTAX
15+
16+
```powershell
17+
Get-TeamViewerInstallationType
18+
```
19+
20+
## DESCRIPTION
21+
22+
The command checks the TeamViewer installation and returns the installation type (Msi, Exe, or Unknown).
23+
24+
## EXAMPLES
25+
26+
### Example 1
27+
28+
```powershell
29+
PS /> Get-TeamViewerInstallationType
30+
```
31+
32+
Returns the installation type of TeamViewer (Msi, Exe, or Unknown).
33+
34+
## PARAMETERS
35+
36+
### CommonParameters
37+
38+
### None
39+
40+
## INPUTS
41+
42+
### None
43+
44+
## OUTPUTS
45+
46+
### System.String
47+
48+
Returns a string indicating the installation type: "Msi", "Exe", or "Unknown".
49+
50+
## NOTES
51+
52+
## RELATED LINKS
53+

Docs/TeamViewerPS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ The following functions are available in this category:
242242

243243
[`Test-TeamViewerInstallation`](Help/Test-TeamViewerInstallation.md)
244244

245+
[`Get-TeamViewerInstallationType`](Help/Get-TeamViewerInstallationType.md)
246+
245247
## Web API Utilities
246248

247249
Utilities that help working with the TeamViewer Web API related functions.
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
BeforeAll {
2+
. "$PSScriptRoot\..\..\Cmdlets\Public\Get-TeamViewerInstallationType.ps1"
3+
@(Get-ChildItem -Path "$PSScriptRoot\..\..\Cmdlets\Private\*.ps1") | `
4+
ForEach-Object { . $_.FullName }
5+
}
6+
7+
Describe 'Get-TeamViewerInstallationType' {
8+
Context 'MsiInstallation - both database and registry present' {
9+
BeforeAll {
10+
Mock Get-CimInstance {
11+
[PSCustomObject]@{ Name = 'TeamViewer' }
12+
}
13+
Mock Get-ItemProperty {
14+
[PSCustomObject]@{ MsiInstallation = 1 }
15+
}
16+
}
17+
18+
It 'Should return Msi when MSI database and MsiInstallation registry value are both present' {
19+
$result = Get-TeamViewerInstallationType
20+
$result | Should -Be 'Msi'
21+
Assert-MockCalled Get-CimInstance -Times 1
22+
}
23+
}
24+
25+
Context 'Msi database found but no registry value' {
26+
BeforeAll {
27+
Mock Get-CimInstance {
28+
[PSCustomObject]@{ Name = 'TeamViewer' }
29+
}
30+
Mock Get-ItemProperty {
31+
throw [System.Management.Automation.ItemNotFoundException]::new()
32+
}
33+
}
34+
35+
It 'Should not return Msi if only database entry exists' {
36+
$result = Get-TeamViewerInstallationType
37+
$result | Should -Not -Be 'Msi'
38+
}
39+
}
40+
41+
Context 'Registry value found but no MSI database entry' {
42+
BeforeAll {
43+
Mock Get-CimInstance {
44+
throw [System.Management.Automation.ItemNotFoundException]::new()
45+
}
46+
Mock Get-ItemProperty {
47+
[PSCustomObject]@{ MsiInstallation = 1 }
48+
}
49+
}
50+
51+
It 'Should not return Msi if only registry value exists' {
52+
$result = Get-TeamViewerInstallationType
53+
$result | Should -Not -Be 'Msi'
54+
}
55+
}
56+
57+
Context 'ExeInstallation with valid UninstallString' {
58+
BeforeAll {
59+
Mock Get-CimInstance {
60+
throw [System.Management.Automation.ItemNotFoundException]::new()
61+
}
62+
Mock Get-ItemProperty {
63+
throw [System.Management.Automation.ItemNotFoundException]::new()
64+
} -ParameterFilter { $Name -eq 'MsiInstallation' }
65+
Mock Test-Path { $true }
66+
Mock Get-ChildItem {
67+
$registryKey = New-Object PSObject
68+
$registryKey | Add-Member -MemberType NoteProperty -Name 'Name' -Value 'TeamViewer'
69+
$registryKey | Add-Member -MemberType NoteProperty -Name 'PSPath' -Value 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\TeamViewer'
70+
$registryKey | Add-Member -MemberType ScriptMethod -Name 'GetValue' -Value { return 'TeamViewer' }
71+
$registryKey
72+
}
73+
Mock Get-ItemProperty {
74+
[PSCustomObject]@{
75+
UninstallString = '"C:\Program Files\TeamViewer\uninstall.exe" /S'
76+
}
77+
} -ParameterFilter { $Name -eq 'UninstallString' }
78+
}
79+
80+
It 'Should return Exe when UninstallString file exists' {
81+
$result = Get-TeamViewerInstallationType
82+
$result | Should -Be 'Exe'
83+
}
84+
}
85+
86+
Context 'Broken ExeInstallation with missing UninstallString file' {
87+
BeforeAll {
88+
Mock Get-CimInstance {
89+
throw [System.Management.Automation.ItemNotFoundException]::new()
90+
}
91+
Mock Get-ItemProperty {
92+
throw [System.Management.Automation.ItemNotFoundException]::new()
93+
} -ParameterFilter { $Name -eq 'MsiInstallation' }
94+
Mock Get-ChildItem {
95+
$registryKey = New-Object PSObject
96+
$registryKey | Add-Member -MemberType NoteProperty -Name 'Name' -Value 'TeamViewer'
97+
$registryKey | Add-Member -MemberType NoteProperty -Name 'PSPath' -Value 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\TeamViewer'
98+
$registryKey | Add-Member -MemberType ScriptMethod -Name 'GetValue' -Value { return 'TeamViewer' }
99+
$registryKey
100+
}
101+
Mock Get-ItemProperty {
102+
[PSCustomObject]@{
103+
UninstallString = '"C:\Program Files\TeamViewer\uninstall.exe" /S'
104+
}
105+
} -ParameterFilter { $Name -eq 'UninstallString' }
106+
107+
Mock Test-Path {
108+
param($Path)
109+
if ($Path -like '*:\Software\*' -or $Path -like '*:\HKEY_*') {
110+
return $true
111+
}
112+
#file does not exist
113+
return $false
114+
}
115+
}
116+
117+
It 'Should return Unknown when UninstallString file does not exist' {
118+
$result = Get-TeamViewerInstallationType
119+
$result | Should -Be 'Unknown'
120+
}
121+
}
122+
123+
Context 'TeamViewer not installed' {
124+
BeforeAll {
125+
Mock Get-CimInstance {
126+
throw [System.Management.Automation.ItemNotFoundException]::new()
127+
}
128+
Mock Get-ItemProperty {
129+
throw [System.Management.Automation.ItemNotFoundException]::new()
130+
}
131+
Mock Get-ChildItem { }
132+
Mock Test-Path { $false }
133+
}
134+
135+
It 'Should return Unknown when TeamViewer is not installed' {
136+
$result = Get-TeamViewerInstallationType
137+
$result | Should -Be 'Unknown'
138+
}
139+
}
140+
141+
Context 'Check both 32-bit and 64-bit registry paths for MSI' {
142+
BeforeAll {
143+
Mock Get-CimInstance {
144+
[PSCustomObject]@{ Name = 'TeamViewer' }
145+
}
146+
Mock Get-ItemProperty {
147+
param($Path)
148+
if ($Path -like '*WOW6432Node*') {
149+
[PSCustomObject]@{ MsiInstallation = 1 }
150+
}
151+
else {
152+
throw [System.Management.Automation.ItemNotFoundException]::new()
153+
}
154+
} -ParameterFilter { $Name -eq 'MsiInstallation' }
155+
}
156+
157+
It 'Should check both registry paths and return Msi if found in WOW6432Node' {
158+
$result = Get-TeamViewerInstallationType
159+
$result | Should -Be 'Msi'
160+
}
161+
}
162+
163+
Context 'Check both uninstall registry paths for Exe' {
164+
BeforeAll {
165+
Mock Get-CimInstance {
166+
throw [System.Management.Automation.ItemNotFoundException]::new()
167+
}
168+
Mock Get-ItemProperty {
169+
throw [System.Management.Automation.ItemNotFoundException]::new()
170+
} -ParameterFilter { $Name -eq 'MsiInstallation' }
171+
Mock Get-ItemProperty {
172+
[PSCustomObject]@{
173+
UninstallString = 'C:\Program Files (x86)\TeamViewer\uninstall.exe /quiet'
174+
}
175+
} -ParameterFilter { $Name -eq 'UninstallString' }
176+
Mock Get-ChildItem {
177+
$registryKey = New-Object PSObject
178+
$registryKey | Add-Member -MemberType NoteProperty -Name 'Name' -Value 'TeamViewer'
179+
$registryKey | Add-Member -MemberType NoteProperty -Name 'PSPath' -Value 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\TeamViewer'
180+
$registryKey | Add-Member -MemberType ScriptMethod -Name 'GetValue' -Value { return 'TeamViewer' }
181+
$registryKey
182+
}
183+
Mock Test-Path { $true }
184+
}
185+
186+
It 'Should check both 64-bit and 32-bit uninstall paths and return Exe' {
187+
$result = Get-TeamViewerInstallationType
188+
$result | Should -Be 'Exe'
189+
}
190+
}
191+
192+
Context 'MSI installation with MsiInstallation value of 0' {
193+
BeforeAll {
194+
Mock Get-CimInstance {
195+
throw [System.Management.Automation.ItemNotFoundException]::new()
196+
}
197+
Mock Get-ItemProperty {
198+
[PSCustomObject]@{ MsiInstallation = 0 }
199+
} -ParameterFilter { $Name -eq 'MsiInstallation' }
200+
Mock Get-ChildItem {
201+
$registryKey = New-Object PSObject
202+
$registryKey | Add-Member -MemberType NoteProperty -Name 'Name' -Value 'TeamViewer'
203+
$registryKey | Add-Member -MemberType NoteProperty -Name 'PSPath' -Value 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\TeamViewer'
204+
$registryKey | Add-Member -MemberType ScriptMethod -Name 'GetValue' -Value { return 'TeamViewer' }
205+
$registryKey
206+
}
207+
Mock Get-ItemProperty {
208+
[PSCustomObject]@{
209+
UninstallString = 'C:\Program Files\TeamViewer\uninstall.exe'
210+
}
211+
} -ParameterFilter { $Name -eq 'UninstallString' }
212+
Mock Test-Path { $true }
213+
}
214+
215+
It 'Should return Exe when MsiInstallation is 0 (ExeInstallation)' {
216+
$result = Get-TeamViewerInstallationType
217+
$result | Should -Be 'Exe'
218+
}
219+
}
220+
}

0 commit comments

Comments
 (0)