Pin icons in system tray with Intune remediation script

What if, on your Intune managed Windows devices, you want certain icons to always remain visible in the system tray? Some icons provide really useful information not just for the user but also for support. Icons like OneDrive, Teams, Defender, and others are ones you might want to keep visible instead of hidden behind the arrow in the system tray. In this post, I’ll show you how to pin icons in the system tray with an Intune remediation script.

Read more: Pin icons in system tray with Intune remediation script

How does the systray visibility work?

All system tray icons, whether hidden or visible, are stored in the registry at HKCU:\Control Panel\NotifyIconSettings. Windows generates a unique key for each icon and assigns several subkeys.

The most important subkey right now is the IsPromoted REG_DWORD subkey, because if it’s present with a value of 1, the icon appears in the visible section of the system tray rather than being hidden behind the arrow.

There is also an executablePath REG_SZ which contains the application’s executable, with the known folder GUID in front of the subfolder and .exe.

Active icons

We want to find out which icons are active and the name of the executables, because knowing the executable’s name and registry location will allow us to create detection and remediation scripts. To view the active icons in the system tray, both visible and hidden behind the arrow, you can run this PowerShell script:

Get-ChildItem "HKCU:\Control Panel\NotifyIconSettings" | ForEach-Object {
    Get-ItemProperty -Path $_.PSPath
} | Select-Object PSChildName, ExecutablePath, IsPromoted | Format-Table -AutoSize


The output displays the ExecutablePath for all the icons currently present and shows the executables name.

Scripts

All that’s left now is to create two scripts: a detection script to verify if the desired icons are visible, and if detection fails, a remediation script to run. The remediation script should also create the IsPromoted REG_DWORD with the associated executable.

I want to always show the icons of the applications: Teams, TrayLight, OneDrive and the SecurityHealthSystray. So we add the executable names in a array and let the script do a check if these executables have got the IsPromoted value 1 subkey. If not the detection failes and then the remediation script will run.

Detection script

# ============================
# Detect-TrayIconsPinned.ps1
# ============================

# Add executables here to keep their tray icon always visible
$targetExes = @(
    "ms-teams.exe",
    "TrayLight.exe",
    "OneDrive.exe",
    "SecurityHealthSystray.exe"
)

$basePath = "HKCU:\Control Panel\NotifyIconSettings"
$subkeys = Get-ChildItem -Path $basePath -ErrorAction SilentlyContinue

$nonCompliant = @()

foreach ($exe in $targetExes) {
    $match = $subkeys | Where-Object {
        (Get-ItemProperty -Path $_.PSPath -ErrorAction SilentlyContinue).ExecutablePath -like "*$exe"
    }

    if (-not $match) {
        $nonCompliant += "$exe"
        continue
    }

    $props = Get-ItemProperty -Path $match.PSPath -ErrorAction SilentlyContinue
    if ($props.IsPromoted -ne 1) {
        $nonCompliant += $exe
    }
}

if ($nonCompliant.Count -eq 0) {
    exit 0
} else {
    exit 1
}

Remediation script

# ============================
# Remediate-TrayIconsPinned.ps1
# ============================

# Add executables here to keep their tray icon always visible
$targetExes = @(
    "ms-teams.exe",
    "TrayLight.exe",
    "OneDrive.exe",
    "SecurityHealthSystray.exe"
)

$basePath = "HKCU:\Control Panel\NotifyIconSettings"
$subkeys = Get-ChildItem -Path $basePath -ErrorAction SilentlyContinue

$changed = $false
$missing = @()

foreach ($exe in $targetExes) {
    $match = $subkeys | Where-Object {
        (Get-ItemProperty -Path $_.PSPath -ErrorAction SilentlyContinue).ExecutablePath -like "*$exe"
    }

    if (-not $match) {
        $missing += $exe
        continue
    }

    Set-ItemProperty -Path $match.PSPath -Name "IsPromoted" -Value 1 -Type DWord -Force
    $changed = $true
}

if ($changed) {
    Stop-Process -Name explorer -Force
    Start-Sleep -Seconds 2

    if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
        Start-Process explorer.exe
    }
}

if ($missing.Count -gt 0) {
    exit 1
} else {
    exit 0
}

So if you want to add other icons just check the executable names and add them to the array in both scripts.

# Add executables here to keep their tray icon always visible
$targetExes = @(
    "ms-teams.exe",
    "TrayLight.exe",
    "OneDrive.exe",
    "SecurityHealthSystray.exe"
)

Create Remediation Intune

Now lets create the detection and remediation in intune for deployment. First save the Detection and Remediation scripts as a PowerShell script.

Go to > Intune portal > Devices > Scripts and remediations > Create

Enter a Name and a Description.

Click Next.

Select the Detection script file and the Remediation script file and set Run this script using the logged-on credentials to Yes.

Click Next and add a scope tag if required and click Next.

Select a group to assign the remediation to and set the schedule how often the remediation should run and click Next and then Create.

User experience


Before remediation no icons are always visible only behind the arrow.

After remediation the icons we set in the array of the remediation script are visiable in the system tray.