Skip to content

Commit 49a3c24

Browse files
Squashed commit of the following:
commit 33f3d0b Author: Donna Ryan <[email protected]> Date: Wed Mar 26 15:17:12 2025 -0400 Initial Commit Includes both detection and remediation script, plus readme.md files
1 parent 3eff28f commit 49a3c24

File tree

3 files changed

+423
-0
lines changed

3 files changed

+423
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<#
2+
.COPYRIGHT
3+
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
4+
See LICENSE in the project root for license information.
5+
#>
6+
7+
# Remote Desktop Multimedia Redirection updater - Detection Script
8+
# Version 0.0.1
9+
10+
#####################################
11+
12+
Param(
13+
[parameter(mandatory = $false, HelpMessage = "Log path and file name")]
14+
[string]$logpath = "$env:windir\temp\RDMMR-detect.log"
15+
)
16+
17+
#Retrieves the version number of the current MMR client
18+
function get-CurrentMMRver {
19+
20+
$response = (Invoke-WebRequest -Uri "https://aka.ms/avdmmr/msi" -UseBasicParsing)
21+
$versionC = $response.BaseResponse.ResponseUri.AbsolutePath -replace ".*HostInstaller_", "" -replace ".x64.msi*", ""
22+
$string = "The latest available version of the RD MMR client is " + $versionC
23+
update-log -Data $string -Class Information -output both
24+
return $versionC
25+
}
26+
27+
#Retrieves the version of MMR installed on the Cloud PC
28+
function get-installedMMRver{
29+
if ((Test-Path -Path 'C:\Program Files\MsRDCMMRHost\MsMmrHost.exe') -eq $true){
30+
$version = (Get-ItemProperty -Path 'C:\Program Files\MsRDCMMRHost\MsMmrHost.exe')
31+
$string = "The currently installed version of the RD MMR client is " + $version.VersionInfo.ProductVersion
32+
update-log -Data $string -Class Information -output both
33+
return $version.VersionInfo.ProductVersion
34+
}
35+
else
36+
{
37+
update-log -data "It doesn't appear that the MMR client is installed" -Class Warning -output both
38+
return "0"}
39+
}
40+
41+
#Logging function
42+
function update-log {
43+
Param(
44+
[Parameter(
45+
Mandatory = $true,
46+
ValueFromPipeline = $true,
47+
ValueFromPipelineByPropertyName = $true,
48+
Position = 0
49+
)]
50+
[string]$Data,
51+
[validateset('Information', 'Warning', 'Error', 'Comment')]
52+
[string]$Class = "Information",
53+
[validateset('Console', 'File', 'Both')]
54+
[string]$Output
55+
)
56+
57+
$date = get-date -UFormat "%m/%d/%y %r"
58+
$String = $Class + " " + $date + " " + $data
59+
if ($Output -eq "Console") { Write-Output $string | out-host }
60+
if ($Output -eq "file") { Write-Output $String | out-file -FilePath $logpath -Append }
61+
if ($Output -eq "Both") {
62+
Write-Output $string | out-host
63+
Write-Output $String | out-file -FilePath $logpath -Append
64+
}
65+
66+
}
67+
68+
#Writes the header of the log
69+
update-log -Data " " -Class Information -output both
70+
update-log -Data "*** Starting RD MMR agent detection ***" -Class Information -output both
71+
update-log -Data " " -Class Information -output both
72+
73+
74+
$MMRCurrent = get-CurrentMMRver
75+
76+
#Calls the function to get the installed version number
77+
$MMRInstalled = get-installedMMRver -Erroraction SilentlyContinue
78+
79+
#Handles the error code if Web RTC client is not installed.
80+
if ($MMRInstalled -eq $null) {
81+
82+
update-log -Data "RD MMR client was not detected. Returning Non-compliant" -Class Warning -output both
83+
Exit 1
84+
}
85+
86+
#Handles the error code if the Web RTC client is out of date.
87+
if ($MMRInstalled -lt $MMRCurrent) {
88+
89+
update-log -Data "RD MMR was detected to be out of date. Returning Non-compliant" -Class Warning -output both
90+
Exit 1
91+
}
92+
93+
#Handles the error code if the installed agent is newer than the latest available client. (shouldn't happen)
94+
if ($MMRInstalled -gt $MMRCurrent) {
95+
96+
update-log -data "The installed version is newer than what is available." -Class Warning -output both
97+
exit 1
98+
}
99+
100+
#Handles the error code if the agent is current.
101+
if ($MMRInstalled -eq $MMRCurrent) {
102+
103+
update-log -Data "The RD MMR client is current. Returning Compliant" -Class Information -output both
104+
Exit 0
105+
}
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
<#
2+
.COPYRIGHT
3+
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
4+
See LICENSE in the project root for license information.
5+
#>
6+
7+
# Remote Desktop Multimedia Redirection updater - Remediation Script
8+
# Version 0.0.1
9+
10+
#####################################
11+
12+
Param(
13+
[parameter(mandatory = $false, HelpMessage = "Log path and file name")]
14+
[string]$logpath = "$env:windir\temp\TeamsWebRTC-remediate.log",
15+
[parameter(mandatory = $false, HelpMessage = "time to wait past disconnect")]
16+
[string]$DCNTwait = 600,
17+
[parameter(mandatory = $false, HelpMessage = "time to wait to re-check user state")]
18+
[string]$StateDetWait = 300,
19+
[parameter(mandatory = $false, HelpMessage = "evaluate user state only once")]
20+
[switch]$retry,
21+
[parameter(mandatory = $false, HelpMessage = "time in minutes to timeout")]
22+
[int]$TimeOut = 60
23+
)
24+
25+
#function to handle logging
26+
function update-log {
27+
Param(
28+
[Parameter(
29+
Mandatory = $true,
30+
ValueFromPipeline = $true,
31+
ValueFromPipelineByPropertyName = $true,
32+
Position = 0
33+
)]
34+
[string]$Data,
35+
[validateset('Information', 'Warning', 'Error', 'Comment')]
36+
[string]$Class = "Information",
37+
[validateset('Console', 'File', 'Both')]
38+
[string]$Output
39+
)
40+
41+
$date = get-date -UFormat "%m/%d/%y %r"
42+
$String = $Class + " " + $date + " " + $data
43+
if ($Output -eq "Console") { Write-Output $string | out-host }
44+
if ($Output -eq "file") { Write-Output $String | out-file -FilePath $logpath -Append }
45+
if ($Output -eq "Both") {
46+
Write-Output $string | out-host
47+
Write-Output $String | out-file -FilePath $logpath -Append
48+
}
49+
}
50+
51+
#function to query the user state and convert to variable
52+
function get-userstate {
53+
(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
54+
if ($_.Split(',').Count -eq 5) {
55+
Write-Output ($_ -replace '(^[^,]+)', '$1,')
56+
}
57+
else {
58+
Write-Output $_
59+
}
60+
} | ConvertFrom-Csv
61+
}
62+
63+
#function to perform the upgrading
64+
function invoke-remediation {
65+
66+
$MMRCurrent = get-CurrentMMRver
67+
68+
$MMRInstalled = get-installedMMRver
69+
$string = "Installed MMR agent version is " + $MMRInstalled
70+
update-log -Data $string -Class Information -Output Both
71+
$string = "Latest version of MMR agent is " + $MMRCurrent
72+
update-log -Data $string -Class Information -Output Both
73+
74+
try {
75+
76+
#Create a directory to save download files
77+
$tempCreated = $false
78+
if (!(Test-Path C:\RDMMRtemp)) {
79+
New-Item -Path C:\ -ItemType Directory -Name RDMMRtemp | Out-Null
80+
update-log -data "Temp path created" -output both -Class Information
81+
$tempCreated = $true
82+
}
83+
84+
#Download MMR
85+
update-log -Data "Downloading RD MMR client" -Class Information -output both
86+
invoke-WebRequest -Uri "https://aka.ms/avdmmr/msi" -OutFile "C:\RDMMRtemp\MMR_Installer.msi" -UseBasicParsing -PassThru
87+
88+
#Install MMR
89+
update-log -Data "Installing RD MMR client" -Class Information -output both
90+
$msireturn = Start-Process msiexec.exe -ArgumentList '/i C:\RDMMRtemp\MMR_Installer.msi /q /n /l*voicewarmup c:\windows\temp\RDMMRmsi.log' -Wait -PassThru
91+
if ($msireturn.ExitCode -eq '0') {
92+
update-log -data "MSIEXEC returned 0" -Class Information -Output Both
93+
}
94+
else {
95+
$string = "MSIEXEC returned exit code " + $msireturn.ExitCode
96+
update-log -data $string -Class Information -Output Both
97+
exit 1
98+
}
99+
100+
if ($tempCreated -eq $true) {
101+
#Remove temp folder
102+
update-log -Data "Removing temp directory" -Class Information -output both
103+
Remove-Item -Path C:\RDMMRtemp\ -Recurse | out-null
104+
}
105+
else {
106+
#Remove downloaded WebRTC file
107+
update-log -Data "Removing RD MMR client installer file" -Class Information -output both
108+
Remove-Item -Path C:\RDMMRtemp\MsRdcWebRTCSvc_HostSetup.msi
109+
}
110+
#Return Success
111+
update-log -Data "Media Optimization Installed" -Class Information -output both
112+
$MMRCurrent = get-CurrentMMRver
113+
$string = "Current installed version is now " + $MMRCurrent
114+
update-log -Data $string -Class Information -Output Both
115+
return "Success"
116+
}
117+
catch {
118+
Write-Error -ErrorRecord $_
119+
return /b "Fail"
120+
}
121+
}
122+
123+
#function to handle user state detection logic
124+
function invoke-userdetect {
125+
update-log -data "Detecting user state." -Class Information -output both
126+
$explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
127+
if ($explorerprocesses.Count -eq 0) {
128+
update-log -data "There is not a user logged in. Skipping user state detection." -Class Information -Output both
129+
Return
130+
}
131+
else {
132+
foreach ($i in $explorerprocesses) {
133+
$Username = $i.GetOwner().User
134+
$Domain = $i.GetOwner().Domain
135+
$string = $Domain + "\" + $Username + " logged on since: " + ($i.ConvertToDateTime($i.CreationDate))
136+
update-log -data $string -Class Information -Output Both
137+
}
138+
update-log -data "There is a logged on user" -Class Information -Output Both
139+
}
140+
141+
if ($retry -eq $true) {
142+
do {
143+
$session = get-userstate
144+
$text = "Waiting for non-active user state."
145+
update-log -data $text -Class Information -output both
146+
$String = "Session State is " + $session.STATE
147+
update-log -data $String -output both -Class Information
148+
$string = "Idle Time is " + $session.'IDLE TIME'
149+
update-log -data $String -output both -Class Information
150+
151+
if ($TimeOut -gt 0) {
152+
sleep -Seconds $StateDetWait
153+
$TimeOut = ($TimeOut - $StateDetWait)
154+
}
155+
else {
156+
update-log -Data "Timed out. Returning fail" -Class Error -output both
157+
return 3
158+
}
159+
} while ($session.state -eq "Active")
160+
161+
update-log -data "User state is not active." -output both -Class Information
162+
invoke-disctimer
163+
}
164+
165+
if ($retry -eq $false) {
166+
update-log -Data "Attempting to detect only once." -Class Information -output both
167+
$session = get-userstate
168+
if ($session.state -eq "disc") {
169+
$text = "User state is disconnected"
170+
update-log -data $text -Class Information -output both
171+
}
172+
else {
173+
update-log -Data "User state is not disconnected" -Class Warning -output both
174+
return 2
175+
}
176+
}
177+
}
178+
179+
#function to handle wait time between first non-active discovery and upgrade
180+
function invoke-disctimer {
181+
$string = "Waiting " + $DCNTwait + " seconds..."
182+
update-log -Data $string -Class Information -output both
183+
sleep -Seconds $DCNTwait
184+
$Timeout = ($Timeout - $DCNTwait)
185+
186+
$session = get-userstate
187+
if ($session.STATE -eq "Active") {
188+
update-log -Data "User state has become active again. Waiting for non-active state..." -Class Warning -output both
189+
invoke-userdetect
190+
}
191+
else {
192+
update-log -data "Session state is still non-active. Continuing with remediation..." -Class Information -output both
193+
}
194+
}
195+
196+
#function to query the latest available version number of RD MMR client
197+
function get-CurrentMMRver {
198+
$response = (Invoke-WebRequest -Uri "https://aka.ms/avdmmr/msi" -UseBasicParsing)
199+
$versionC = $response.BaseResponse.ResponseUri.AbsolutePath -replace ".*HostInstaller_", "" -replace ".x64.msi*", ""
200+
$string = "The latest available version of the RD MMR client is " + $versionC
201+
update-log -Data $string -Class Information -output both
202+
return $versionC
203+
}
204+
205+
#function to determine what version of RDMMR is installed
206+
function get-installedMMRver{
207+
if ((Test-Path -Path 'C:\Program Files\MsRDCMMRHost\MsMmrHost.exe') -eq $true){
208+
$version = (Get-ItemProperty -Path 'C:\Program Files\MsRDCMMRHost\MsMmrHost.exe')
209+
$string = "The currently installed version of the RD MMR client is " + $version.VersionInfo.ProductVersion
210+
update-log -Data $string -Class Information -output both
211+
return $version.VersionInfo.ProductVersion
212+
}
213+
else
214+
{
215+
update-log -data "It doesn't appear that the RD MMR client is installed" -Class Warning -output both
216+
return "0"}
217+
}
218+
219+
#Opening text of log.
220+
update-log -Data " " -Class Information -output both
221+
update-log -Data "*** Starting RD MMR agent remediation ***" -Class Information -output both
222+
update-log -Data " " -Class Information -output both
223+
224+
#Display timeout amount in the log - if using retry function
225+
if ($retry -eq $true) {
226+
$String = "Time out set for " + $Timeout + " minutes"
227+
update-log -Data $String -output both -Class Information
228+
}
229+
230+
#Converts Timeout minutes to seconds
231+
$TimeOut = $TimeOut * 60
232+
233+
#Starts the user state detection and handling
234+
$var1 = invoke-userdetect
235+
236+
# Exit if user is active (default).
237+
#Return code for no retry - user is active
238+
if ($var1 -eq 2) {
239+
update-log -Data "User State is active. Returning fail. Try again" -Class Warning -output both
240+
exit 1
241+
}
242+
243+
#Exit if process times out. Used with "-retry" parameter.
244+
#Return code for time out
245+
if ($var1 -eq 3) {
246+
update-log -Data "Timed out. Returning fail. Try again" -Class Warning -output both
247+
exit 1
248+
}
249+
250+
#Starts the remediaiton function
251+
$result = $null
252+
$result = invoke-remediation
253+
254+
#Exit if the remediation was successful
255+
if ($result -eq "Success") {
256+
update-log -Data "Remediation Complete" -Class Information -output both
257+
exit 0
258+
}
259+
260+
#Exit if remediation failed
261+
if ($result -ne "Success") {
262+
update-log -Data "An error occured." -Class Error -output both
263+
exit 1
264+
}
265+

0 commit comments

Comments
 (0)