> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://help.trugrid.com/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# TruGrid SecureRDP - Teams meetings optimization

## Contents

1. [Overview](#3-overview)
2. [Prerequisites](#2-prerequisites)
3. [What needs to be configured](#2-what-needs-to-be-configured)
4. [How to run the scripts](#2-how-to-run-the-scripts)
5. [Setting Remote Desktop as the default RDP client](#2-setting-remote-desktop-as-the-default-rdp-client)
6. [Verification](#2-verification)
7. [Troubleshooting](#2-troubleshooting)
8. [Endpoint script](#2-endpoint-script)
9. [Session host script](#2-session-host-script)


| For ease of deployment, we recommend using the [TruGrid SecureRDP - Windows Toolkit](https://help.trugrid.com/en/article/trugrid-securerdp-windows-toolkit-1xejitj/) to perform the Client/Host optimizations. 

## Overview

Microsoft Teams runs unoptimized inside an RDP session by default - audio and video are rendered remotely and forwarded across the connection, adding latency and bandwidth cost. With media redirection, Teams audio and video run on the local endpoint while the rest of Teams lives in the remote session.
Configuration is needed on two sides:
* The **endpoint** - the machine where the TruGrid Windows Connector is installed and the user starts RDP sessions from
* The **session host** - the machine the user RDPs into
Each side has its own script. Both must be run for media optimization to work.

## Prerequisites

* Windows 10 22H2 or Windows 11 (endpoint); Windows 10 22H2, Windows 11, or Windows Server 2019/2022 with the RDS role (session host)
* Local administrator rights on each machine
* Internet access for installer downloads
* A custom build of the TruGrid Windows Connector that launches sessions in the Remote Desktop client rather than `mstsc`. This is available upon request from TruGrid support. The standard Connector cannot perform media optimization regardless of the components installed below.

## What needs to be configured

### On the endpoint
| Item | Why it's needed | How the script handles it |
| ---- |
| Microsoft Visual C++ Redistributable (x64) | Required runtime for the WebRTC redirector | Silent install |
| Remote Desktop client (MSRDC, MSI install) | RDP client that supports Teams media optimization (`mstsc` does not) | Silent install via Microsoft's per-machine MSI |
| Remote Desktop WebRTC redirector | Local-side WebRTC stack for redirected Teams media | Silent MSI install |
| Default `.rdp` handler set to Remote Desktop | Ensures `.rdp` files open with the new client, not `mstsc` | Opens Settings > Default Apps for the .rdp file type |

### On the session host
| Item | Why it's needed | How the script handles it |
| ---- |
| Microsoft Visual C++ Redistributable (x64) | Required runtime for Teams and the WebRTC redirector | Silent install |
| New Teams (per-machine install) | Multi-user installation of the new Teams client | Silent install via Microsoft's bootstrapper + MSIX |
| Remote Desktop WebRTC redirector | Server-side WebRTC stack for redirected media | Silent MSI install |
| `IsWVDEnvironment` registry value | Tells Teams it is running in a redirected environment | Sets the DWORD to `1` at `HKLM\SOFTWARE\Microsoft\Teams` |

## How to run the scripts

| We recommend using the [TruGrid SecureRDP - Windows Toolkit](https://help.trugrid.com/en/article/trugrid-securerdp-windows-toolkit-1xejitj/) to perform the Client/Host optimizations. 

### Recommended: PowerShell ISE

1. Right-click **Windows PowerShell ISE** and choose **Run as administrator**.
2. Paste the entire script (from the sections at the bottom of this article) into a new script pane.
3. Press **F5** to run.

The script checks the current state of each item, displays a status report, and prompts you in the console pane before installing anything. To run with different behavior, change the `param` block at the top of the script before pressing F5:
* Default (no changes): interactive - prompts before installing
* Set `[switch]$CheckOnly = $true` in the param block: status report only, no install
* Set `[switch]$Apply = $true` in the param block: install everything missing without prompting
Run the endpoint script on the endpoint machine and the session host script on the session host machine. They are not interchangeable.

### Setting Remote Desktop as the default RDP client

Windows blocks programmatic changes to file-type defaults as a security measure - the endpoint script cannot directly set Remote Desktop as the default for `.rdp` files. When this step is needed, the script opens Settings > Default Apps for the `.rdp` file type and waits for you to make the change.
In the dialog that appears:
1. Find the entry showing the current default app for `.rdp` files (likely "Remote Desktop Connection" / `mstsc`)
2. Click it
3. Select **Remote Desktop** from the list - the entry corresponding to the MSRDC client, not "Remote Desktop Connection" (the classic `mstsc` entry)
4. Click **Set default**
5. Close Settings and return to the script. Press Enter to continue.

After this change, double-clicking any `.rdp` file - whether from TruGrid or any other source - will open in the modern Remote Desktop client rather than the classic Remote Desktop Connection.
If Remote Desktop does not appear in the list of available defaults, confirm the previous step succeeded - the MSI install should have placed `msrdc.exe` (and `msrdcw.exe`) under `C:\Program Files\Remote Desktop` or the equivalent per-user path.

## Verification

After both scripts have completed and the session host has been signed out and signed back in (the `IsWVDEnvironment` registry value is read at Teams startup), start a TruGrid RDP session from the endpoint into the session host. The session should now open in the Remote Desktop client rather than the classic `mstsc` window.
Inside the session, open Teams and start a call. In the call window, click the three-dot menu, then **About > Version**. The dialog should indicate "Media optimized for Virtual Desktop" or similar. If the indicator is missing, sign out of the session and back in once, then re-check.

## Troubleshooting

**Endpoint script reports the Remote Desktop client as missing after install.** The MSI install completed but the binaries went somewhere unexpected. Check for `msrdc.exe` and `msrdcw.exe` under `C:\Program Files\Remote Desktop` (per-machine) or `%LocalAppData%\Apps\Remote Desktop` (per-user).

**Default&#32;`.rdp`&#32;handler still shows&#32;`mstsc`&#32;after Settings change.** Sign out and back in to the endpoint. Some default-app changes do not take effect for the current shell session.

**Alternatively **you can create a test file by opening an Remote Desktop App and click Save As and store the temporary file on the Dekstop > then make a right click find Open With and select another Remote Desktop Application 

**TruGrid still launches&#32;`mstsc`&#32;despite Remote Desktop being default.** This means the standard TruGrid Connector is in use. The custom build is required - contact support.

**Host script reports New Teams as missing after install.** Classic Teams (per-user) can interfere with detection. Uninstall any per-user Teams installations:
```
Get-AppxPackage -AllUsers MicrosoftTeams | Remove-AppxPackage -AllUsers
```
Then re-run the host script.

**`IsWVDEnvironment`&#32;set but optimization indicator missing in Teams.** Confirm Teams was restarted after the registry change. The value is read at process startup, not continuously. Also confirm the endpoint side is using the Remote Desktop client, not `mstsc`.

**Teams audio still routes through the session after sign-out and sign-in.** Verify the `MsRdcWebRtcSvc` service exists and is set to start automatically on both sides:
```
Get-Service MsRdcWebRtcSvc | Select-Object Status, StartType
```
**A script reports&#32;`[ STILL MISSING ]`&#32;for any item in the final summary.** Scroll up to the install step output for that item - the script logs the installer's exit code and any error inline.

## Endpoint script

Save as `Optimize-TeamsForRdp-Client.ps1` and run on the endpoint.

```
# Optimize-TeamsForRdp-Client.ps1
# Configures a Windows machine acting as a TruGrid Connector endpoint for
# optimized Teams-over-RDP. Reference:
# https://learn.microsoft.com/en-us/azure/virtual-desktop/teams-on-avd

[CmdletBinding()]
param(
    [switch]$Apply,
    [switch]$CheckOnly
)

$ConfirmPreference = 'None'
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'

# --- Elevation check ---------------------------------------------------------

$id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [System.Security.Principal.WindowsPrincipal]::new($id)
if (-not $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Host "ERROR: This script must be run from an elevated PowerShell session." -ForegroundColor Red
    Write-Host "Right-click PowerShell -> Run as administrator, then re-run this script."
    return
}

$cacheDir = Join-Path $env:TEMP 'TruGrid-TeamsOptimization'
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null

# --- Win32 P/Invoke for file association lookup ------------------------------

if (-not ('Assoc' -as [type])) {
    Add-Type @"
using System;
using System.Runtime.InteropServices;
using System.Text;
public class Assoc {
    [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
    public static extern uint AssocQueryString(uint flags, uint str, string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
}
"@
}

# --- Check functions ---------------------------------------------------------

function Get-VcRedistStatus {
    $key = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64' -ErrorAction SilentlyContinue
    if ($key -and $key.Installed -eq 1) {
        @{ Installed = $true; Detail = "v$($key.Version)" }
    } else {
        @{ Installed = $false; Detail = 'Not found' }
    }
}

function Get-RemoteDesktopClientStatus {
    # The Microsoft Desktop client (msrdc.exe / msrdcw.exe), installed via MSI
    foreach ($path in @(
        'C:\Program Files\Remote Desktop\msrdc.exe',
        'C:\Program Files\Remote Desktop\msrdcw.exe',
        (Join-Path $env:LOCALAPPDATA 'Apps\Remote Desktop\msrdc.exe'),
        (Join-Path $env:LOCALAPPDATA 'Apps\Remote Desktop\msrdcw.exe')
    )) {
        if (Test-Path $path) {
            $ver = (Get-Item $path).VersionInfo.FileVersion
            $scope = if ($path -like "$env:LOCALAPPDATA*") { 'Per-user' } else { 'Per-machine' }
            return @{ Installed = $true; Detail = "$scope v$ver ($([System.IO.Path]::GetFileName($path)))" }
        }
    }
    @{ Installed = $false; Detail = 'Not installed' }
}

function Get-WebRtcStatus {
    $svc = Get-Service 'MsRdcWebRtcSvc' -ErrorAction SilentlyContinue
    $file = Test-Path 'C:\Program Files\Remote Desktop WebRTC Redirector\MsRdcWebRtcSvc.exe'
    if ($svc -or $file) {
        @{ Installed = $true; Detail = if ($svc) { "Service: $($svc.Status)" } else { 'File present' } }
    } else {
        @{ Installed = $false; Detail = 'Not installed' }
    }
}

function Get-DefaultRdpHandlerStatus {
    # Use the actual Win32 API Explorer uses (AssocQueryString) - authoritative
    $buf = New-Object Text.StringBuilder 260
    $size = [uint32]260
    # ASSOCSTR_EXECUTABLE = 2
    [void][Assoc]::AssocQueryString(0, 2, '.rdp', 'open', $buf, [ref]$size)
    $path = $buf.ToString()
    $exe = [System.IO.Path]::GetFileName($path)

    if ($exe -match 'msrdc(w)?\.exe') {
        @{ Installed = $true; Detail = "Handler: $exe ($path)" }
    } elseif ($exe -match 'mstsc\.exe') {
        @{ Installed = $false; Detail = "Currently mstsc.exe (legacy)" }
    } elseif (-not $exe) {
        @{ Installed = $false; Detail = 'No association resolved' }
    } else {
        @{ Installed = $false; Detail = "Unknown handler: $exe" }
    }
}

# --- Install functions -------------------------------------------------------

function Install-VcRedist {
    $url = 'https://aka.ms/vs/17/release/vc_redist.x64.exe'
    $target = Join-Path $cacheDir 'vc_redist.x64.exe'
    Write-Host "  Downloading from $url..." -NoNewline
    Invoke-WebRequest -Uri $url -OutFile $target -UseBasicParsing
    Write-Host " done."
    Write-Host "  Running silent install..." -NoNewline
    $proc = Start-Process -FilePath $target -ArgumentList '/install','/quiet','/norestart' -Wait -PassThru
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0 -and $proc.ExitCode -ne 3010) {
        throw "VC++ Redist installer failed with exit $($proc.ExitCode)"
    }
}

function Install-RemoteDesktopClient {
    # Per-machine MSI - silent install, no user interaction
    $url = 'https://go.microsoft.com/fwlink/?linkid=2139369'
    $target = Join-Path $cacheDir 'RemoteDesktop_x64.msi'
    Write-Host "  Downloading Remote Desktop client (per-machine MSI)..." -NoNewline
    Invoke-WebRequest -Uri $url -OutFile $target -UseBasicParsing
    Write-Host " done."
    Write-Host "  Running silent install..." -NoNewline
    $proc = Start-Process msiexec.exe -ArgumentList "/i `"$target`"",'/qn','/norestart' -Wait -PassThru
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0 -and $proc.ExitCode -ne 3010) {
        throw "Remote Desktop client install failed with exit $($proc.ExitCode)"
    }
}

function Install-WebRtc {
    $url = 'https://aka.ms/msrdcwebrtcsvc/msi'
    $target = Join-Path $cacheDir 'MsRdcWebRtcSvc.msi'
    Write-Host "  Downloading from $url..." -NoNewline
    Invoke-WebRequest -Uri $url -OutFile $target -UseBasicParsing
    Write-Host " done."
    Write-Host "  Running silent install..." -NoNewline
    $proc = Start-Process msiexec.exe -ArgumentList "/i `"$target`"",'/qn','/norestart' -Wait -PassThru
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0 -and $proc.ExitCode -ne 3010) {
        throw "WebRTC MSI install failed with exit $($proc.ExitCode)"
    }
}

function Set-DefaultRdpHandler {
    Write-Host "  Windows blocks programmatic default-app changes for security."
    Write-Host "  Opening Settings > Default Apps for the .rdp file type."
    Write-Host "  In the dialog that appears, select 'Remote Desktop' and click 'Set default'."
    Start-Process 'ms-settings:defaultapps?extension=.rdp'
    Write-Host "  Press ENTER once Remote Desktop is selected as the default..."
    [void](Read-Host)
}

# --- Status report -----------------------------------------------------------

Write-Host ""
Write-Host "TruGrid - Teams Optimization (Endpoint / Client)" -ForegroundColor Cyan
Write-Host "================================================="
Write-Host ""

$vcRedist = Get-VcRedistStatus
$rdClient = Get-RemoteDesktopClientStatus
$webRtc = Get-WebRtcStatus
$defaultHandler = Get-DefaultRdpHandlerStatus

$items = @(
    @{ Name = 'VC++ Redistributable (x64)';                 Status = $vcRedist;       Installer = 'Install-VcRedist' }
    @{ Name = 'Remote Desktop client (MSI)';                Status = $rdClient;       Installer = 'Install-RemoteDesktopClient' }
    @{ Name = 'Remote Desktop WebRTC';                      Status = $webRtc;         Installer = 'Install-WebRtc' }
    @{ Name = 'Default .rdp handler set to Remote Desktop'; Status = $defaultHandler; Installer = 'Set-DefaultRdpHandler' }
)

foreach ($i in $items) {
    $tag = if ($i.Status.Installed) { '[ OK    ]' } else { '[ MISSING ]' }
    $color = if ($i.Status.Installed) { 'Green' } else { 'Yellow' }
    Write-Host "  $tag  $($i.Name) - $($i.Status.Detail)" -ForegroundColor $color
}

Write-Host ""
Write-Host "  [ NOTE  ]  Custom TruGrid Connector build (Remote Desktop routing)" -ForegroundColor Cyan
Write-Host "             Required so TruGrid launches sessions in Remote Desktop instead of mstsc."
Write-Host "             Open a ticket with TruGrid support to obtain it."
Write-Host ""

$missing = $items | Where-Object { -not $_.Status.Installed }

if ($missing.Count -eq 0) {
    Write-Host "All checked items satisfied. No action needed." -ForegroundColor Green
    return
}

if ($CheckOnly) {
    Write-Host "$($missing.Count) item(s) need attention. Re-run without -CheckOnly to install." -ForegroundColor Yellow
    return
}

Write-Host "$($missing.Count) item(s) need to be installed or configured:" -ForegroundColor Yellow
$missing | ForEach-Object { Write-Host "  - $($_.Name)" }
Write-Host ""

if (-not $Apply) {
    $response = Read-Host "Apply fixes now? [Y/N]"
    if ($response -notmatch '^[Yy]') {
        Write-Host "Aborted by user." -ForegroundColor Yellow
        return
    }
}

# --- Apply ------------------------------------------------------------------

foreach ($i in $missing) {
    Write-Host ""
    Write-Host "Applying: $($i.Name)" -ForegroundColor Cyan
    try {
        & $i.Installer
        Write-Host "  Done." -ForegroundColor Green
    } catch {
        Write-Host "  FAILED: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# --- Re-verify --------------------------------------------------------------

Write-Host ""
Write-Host "Re-verifying state..." -ForegroundColor Cyan
Write-Host ""

$finalItems = @(
    @{ Name = 'VC++ Redistributable (x64)';                 Status = (Get-VcRedistStatus) }
    @{ Name = 'Remote Desktop client (MSI)';                Status = (Get-RemoteDesktopClientStatus) }
    @{ Name = 'Remote Desktop WebRTC';                      Status = (Get-WebRtcStatus) }
    @{ Name = 'Default .rdp handler set to Remote Desktop'; Status = (Get-DefaultRdpHandlerStatus) }
)

foreach ($i in $finalItems) {
    $tag = if ($i.Status.Installed) { '[ OK    ]' } else { '[ STILL MISSING ]' }
    $color = if ($i.Status.Installed) { 'Green' } else { 'Red' }
    Write-Host "  $tag  $($i.Name) - $($i.Status.Detail)" -ForegroundColor $color
}

Write-Host ""
Write-Host "Endpoint Teams optimization complete." -ForegroundColor Cyan
Write-Host "Remember to also configure the session host(s) using Optimize-TeamsForRdp-Host.ps1."
Write-Host ""
```

## Session host script

Save as `Optimize-TeamsForRdp-Host.ps1` and run on the session host.
```
# Optimize-TeamsForRdp-Host.ps1
# Configures a Windows machine acting as an RDP Session Host (the machine
# customers RDP into) for optimized Teams. Reference:
# https://learn.microsoft.com/en-us/azure/virtual-desktop/teams-on-avd

[CmdletBinding()]
param(
    [switch]$Apply,
    [switch]$CheckOnly
)

$ConfirmPreference = 'None'
$ProgressPreference = 'SilentlyContinue'
$ErrorActionPreference = 'Stop'

# --- Elevation check ---------------------------------------------------------

$id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [System.Security.Principal.WindowsPrincipal]::new($id)
if (-not $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Host "ERROR: This script must be run from an elevated PowerShell session." -ForegroundColor Red
    Write-Host "Right-click PowerShell -> Run as administrator, then re-run this script."
    return
}

$cacheDir = Join-Path $env:TEMP 'TruGrid-TeamsOptimization'
New-Item -ItemType Directory -Path $cacheDir -Force | Out-Null

# --- Check functions ---------------------------------------------------------

function Get-VcRedistStatus {
    $key = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64' -ErrorAction SilentlyContinue
    if ($key -and $key.Installed -eq 1) {
        @{ Installed = $true; Detail = "v$($key.Version)" }
    } else {
        @{ Installed = $false; Detail = 'Not found' }
    }
}

function Get-NewTeamsStatus {
    # Per-machine "New Teams" provisioning
    $pkg = Get-AppxPackage -AllUsers -Name 'MSTeams' -ErrorAction SilentlyContinue
    if ($pkg) {
        @{ Installed = $true; Detail = "v$($pkg.Version) (per-machine)" }
    } else {
        @{ Installed = $false; Detail = 'Not installed per-machine' }
    }
}

function Get-WebRtcStatus {
    $svc = Get-Service 'MsRdcWebRtcSvc' -ErrorAction SilentlyContinue
    $file = Test-Path 'C:\Program Files\Remote Desktop WebRTC Redirector\MsRdcWebRtcSvc.exe'
    if ($svc -or $file) {
        @{ Installed = $true; Detail = if ($svc) { "Service: $($svc.Status)" } else { 'File present' } }
    } else {
        @{ Installed = $false; Detail = 'Not installed' }
    }
}

function Get-WvdRegistryStatus {
    $val = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Teams' -ErrorAction SilentlyContinue).IsWVDEnvironment
    if ($val -eq 1) {
        @{ Installed = $true; Detail = 'IsWVDEnvironment = 1' }
    } else {
        @{ Installed = $false; Detail = if ($null -eq $val) { 'Key/value missing' } else { "IsWVDEnvironment = $val" } }
    }
}

# --- Install functions -------------------------------------------------------

function Install-VcRedist {
    $url = 'https://aka.ms/vs/17/release/vc_redist.x64.exe'
    $target = Join-Path $cacheDir 'vc_redist.x64.exe'
    Write-Host "  Downloading from $url..." -NoNewline
    Invoke-WebRequest -Uri $url -OutFile $target -UseBasicParsing
    Write-Host " done."
    Write-Host "  Running silent install..." -NoNewline
    $proc = Start-Process -FilePath $target -ArgumentList '/install','/quiet','/norestart' -Wait -PassThru
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0 -and $proc.ExitCode -ne 3010) {
        throw "VC++ Redist installer failed with exit $($proc.ExitCode)"
    }
}

function Install-NewTeams {
    $bootstrapperUrl = 'https://go.microsoft.com/fwlink/?linkid=2243204&clcid=0x409'
    $msixUrl = 'https://go.microsoft.com/fwlink/?linkid=2196106'
    $bootstrapper = Join-Path $cacheDir 'teamsbootstrapper.exe'
    $msix = Join-Path $cacheDir 'MSTeams-x64.msix'

    Write-Host "  Downloading Teams bootstrapper..." -NoNewline
    Invoke-WebRequest -Uri $bootstrapperUrl -OutFile $bootstrapper -UseBasicParsing
    Write-Host " done."

    Write-Host "  Downloading Teams MSIX..." -NoNewline
    Invoke-WebRequest -Uri $msixUrl -OutFile $msix -UseBasicParsing
    Write-Host " done."

    Write-Host "  Running per-machine provisioning..." -NoNewline
    $proc = Start-Process -FilePath $bootstrapper -ArgumentList '-p','-o',"`"$msix`"" -Wait -PassThru -NoNewWindow
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0) {
        throw "Teams bootstrapper failed with exit $($proc.ExitCode)"
    }
}

function Install-WebRtc {
    $url = 'https://aka.ms/msrdcwebrtcsvc/msi'
    $target = Join-Path $cacheDir 'MsRdcWebRtcSvc.msi'
    Write-Host "  Downloading from $url..." -NoNewline
    Invoke-WebRequest -Uri $url -OutFile $target -UseBasicParsing
    Write-Host " done."
    Write-Host "  Running silent install..." -NoNewline
    $proc = Start-Process msiexec.exe -ArgumentList "/i `"$target`"",'/qn','/norestart' -Wait -PassThru
    Write-Host " exit $($proc.ExitCode)."
    if ($proc.ExitCode -ne 0 -and $proc.ExitCode -ne 3010) {
        throw "WebRTC MSI install failed with exit $($proc.ExitCode)"
    }
}

function Set-WvdRegistry {
    New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Teams' -Force | Out-Null
    New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Teams' `
        -Name IsWVDEnvironment -PropertyType DWORD -Value 1 -Force | Out-Null
    Write-Host "  Registry value set."
}

# --- Status report -----------------------------------------------------------

Write-Host ""
Write-Host "TruGrid - Teams Optimization (Session Host)" -ForegroundColor Cyan
Write-Host "============================================"
Write-Host ""

$vcRedist = Get-VcRedistStatus
$newTeams = Get-NewTeamsStatus
$webRtc = Get-WebRtcStatus
$wvdReg = Get-WvdRegistryStatus

$items = @(
    @{ Name = 'VC++ Redistributable (x64)';        Status = $vcRedist; Installer = 'Install-VcRedist' }
    @{ Name = 'New Teams (per-machine)';           Status = $newTeams; Installer = 'Install-NewTeams' }
    @{ Name = 'Remote Desktop WebRTC';             Status = $webRtc;   Installer = 'Install-WebRtc' }
    @{ Name = 'IsWVDEnvironment registry';         Status = $wvdReg;   Installer = 'Set-WvdRegistry' }
)

foreach ($i in $items) {
    $tag = if ($i.Status.Installed) { '[ OK    ]' } else { '[ MISSING ]' }
    $color = if ($i.Status.Installed) { 'Green' } else { 'Yellow' }
    Write-Host "  $tag  $($i.Name) - $($i.Status.Detail)" -ForegroundColor $color
}

Write-Host ""
$missing = $items | Where-Object { -not $_.Status.Installed }

if ($missing.Count -eq 0) {
    Write-Host "All checked items satisfied. No action needed." -ForegroundColor Green
    return
}

if ($CheckOnly) {
    Write-Host "$($missing.Count) item(s) need attention. Re-run without -CheckOnly to install." -ForegroundColor Yellow
    return
}

Write-Host "$($missing.Count) item(s) need to be installed/configured:" -ForegroundColor Yellow
$missing | ForEach-Object { Write-Host "  - $($_.Name)" }
Write-Host ""

if (-not $Apply) {
    $response = Read-Host "Apply fixes now? [Y/N]"
    if ($response -notmatch '^[Yy]') {
        Write-Host "Aborted by user." -ForegroundColor Yellow
        return
    }
}

# --- Apply ------------------------------------------------------------------

foreach ($i in $missing) {
    Write-Host ""
    Write-Host "Applying: $($i.Name)" -ForegroundColor Cyan
    try {
        & $i.Installer
        Write-Host "  Done." -ForegroundColor Green
    } catch {
        Write-Host "  FAILED: $($_.Exception.Message)" -ForegroundColor Red
    }
}

# --- Re-verify --------------------------------------------------------------

Write-Host ""
Write-Host "Re-verifying state..." -ForegroundColor Cyan
Write-Host ""

$finalItems = @(
    @{ Name = 'VC++ Redistributable (x64)';        Status = (Get-VcRedistStatus) }
    @{ Name = 'New Teams (per-machine)';           Status = (Get-NewTeamsStatus) }
    @{ Name = 'Remote Desktop WebRTC';             Status = (Get-WebRtcStatus) }
    @{ Name = 'IsWVDEnvironment registry';         Status = (Get-WvdRegistryStatus) }
)

foreach ($i in $finalItems) {
    $tag = if ($i.Status.Installed) { '[ OK    ]' } else { '[ STILL MISSING ]' }
    $color = if ($i.Status.Installed) { 'Green' } else { 'Red' }
    Write-Host "  $tag  $($i.Name) - $($i.Status.Detail)" -ForegroundColor $color
}

Write-Host ""
Write-Host "Session Host Teams optimization complete." -ForegroundColor Cyan
Write-Host "A user logon (or reboot) may be needed for Teams to pick up the WVD environment flag."
Write-Host ""
```