Make specific tray icon always show for all profiles in Windows 7

13

6

I'm setting up a Windows 7 machine that will sit out in the open and be shared by a lot of people. I have added a shortcut to the all users start menu to run a program that sits in the system tray. I want the tray icon for this program to always be visible by default, no matter who logs in. A user can turn it off on their profile if they really want to, but I need it to at least start out set as always visible. How can I do this?

I would rather not show all the icons, in part for the same reason they are hidden in the first place: I don't want the clutter. Also, as this is a public computer there is another program called DeepFreeze running that also has a system tray icon, and I don't want that icon to show all the time.

Joel Coehoorn

Posted 2011-08-02T13:41:51.390

Reputation: 26 787

Can't you show the icon/message by some other mechanism than in the system tray? – jalf – 2011-08-02T15:52:35.143

Answers

11

In a nut-shell, currently, you can't do this.

There is no Group Policy or Preference to set this, and the way it keeps track makes it specific to the current user and the system, making the 'settings' vary greatly from instance to instance.

They are stored here (in the registry) if you want to check it out: HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify.

From here:

There is no way for applications to programmatically always show themselves top level on the system tray either on first install or at any time during runtime. This is one of several changes we’ve made in Windows 7 in an effort to produce a cleaner, quieter desktop that is in the user’s control to customize the top level with their favorite applications and icons.

We keep the user in control of the notification area by not allowing programmatic promotion (other than temporarily or to show a notification). Assuming the machine is sufficiently quiet, when you first add your icon with Shell_NotifyIcon(NIM_ADD, ...) it will be shown on the taskbar for 45 seconds, then move into the overflow thereafter. If the user promotes an icon, it will always live on the taskbar. If the user demotes it, the icon will never be seen on the taskbar. Any promotion needs to be user initiated. We’ve made this much easier in Windows 7 via drag/drop & through the Notification Area Icons control panel, and what we’ve seen in usability studies and based on beta feedback, is that users have no difficulties discovering how to customize notification behavior and will promote the icons they want quick access to.

About your easiest bet is to show ALL Notification Area icons for all users. This can be done by adding a (simple) registry entry:

In HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer create a new DWORD value named EnableAutoTray and set it to 0 to turn off the Notification Area's 'auto hide' features.

With some OU configuration and scripting you can use it in a HKCU context as well, if you only want it to happen for certain users/groups.

See here for more info on that.

Ƭᴇcʜιᴇ007

Posted 2011-08-02T13:41:51.390

Reputation: 103 763

I'd rather not show all the icons, but I will if I must. – Joel Coehoorn – 2011-08-02T15:12:03.730

10

I was searching online and actually found this randomly.

Long story short, a combination of PowerShell (script provided) and GPO.

http://4sysops.com/archives/forcing-notification-area-icons-to-always-show-in-windows-7-or-windows-8/

Long story, create a PowerShell script containing the following:

param(
    [Parameter(Mandatory=$true,HelpMessage='The name of the program')][string]$ProgramName,
    [Parameter(Mandatory=$true,HelpMessage='The setting (2 = show icon and notifications 1 = hide icon and notifications, 0 = only show notifications')]
        [ValidateScript({if ($_ -lt 0 -or $_ -gt 2) { throw 'Invalid setting' } return $true})]
        [Int16]$Setting
    )

$encText = New-Object System.Text.UTF8Encoding
[byte[]] $bytRegKey = @()
$strRegKey = ""
$bytRegKey = $(Get-ItemProperty $(Get-Item 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify').PSPath).IconStreams
for($x=0; $x -le $bytRegKey.Count; $x++)
{
    $tempString = [Convert]::ToString($bytRegKey[$x], 16)
    switch($tempString.Length)
    {
        0 {$strRegKey += "00"}
        1 {$strRegKey += "0" + $tempString}
        2 {$strRegKey += $tempString}
    }
}
[byte[]] $bytTempAppPath = @()
$bytTempAppPath = $encText.GetBytes($ProgramName)
[byte[]] $bytAppPath = @()
$strAppPath = ""

Function Rot13($byteToRot)
{
    if($byteToRot -gt 64 -and $byteToRot -lt 91)
    {
        $bytRot = $($($byteToRot - 64 + 13) % 26 + 64)
        return $bytRot
    }
    elseif($byteToRot -gt 96 -and $byteToRot -lt 123)
    {
        $bytRot = $($($byteToRot - 96 + 13) % 26 + 96)
        return $bytRot
    }
    else
    {
        return $byteToRot
    }
}

for($x = 0; $x -lt $bytTempAppPath.Count * 2; $x++)
{
    If($x % 2 -eq 0)
    {
        $curbyte = $bytTempAppPath[$([Int]($x / 2))]
            $bytAppPath += Rot13($curbyte)

    }
    Else
    {
        $bytAppPath += 0
    }
}

for($x=0; $x -lt $bytAppPath.Count; $x++)
{
    $tempString = [Convert]::ToString($bytAppPath[$x], 16)
    switch($tempString.Length)
    {
        0 {$strAppPath += "00"}
        1 {$strAppPath += "0" + $tempString}
        2 {$strAppPath += $tempString}
    }
}
if(-not $strRegKey.Contains($strAppPath))
{
    Write-Host Program not found. Programs are case sensitive.
    break
}

[byte[]] $header = @()
$items = @{}
for($x=0; $x -lt 20; $x++)
{
    $header += $bytRegKey[$x]
}

for($x=0; $x -lt $(($bytRegKey.Count-20)/1640); $x++)
{
    [byte[]] $item=@()
    $startingByte = 20 + ($x*1640)
    $item += $bytRegKey[$($startingByte)..$($startingByte+1639)]
    $items.Add($startingByte.ToString(), $item)
}

foreach($key in $items.Keys)
{
$item = $items[$key]
    $strItem = ""
    $tempString = ""

    for($x=0; $x -le $item.Count; $x++)
    {
        $tempString = [Convert]::ToString($item[$x], 16)
        switch($tempString.Length)
        {
            0 {$strItem += "00"}
            1 {$strItem += "0" + $tempString}
            2 {$strItem += $tempString}
        }
    }
    if($strItem.Contains($strAppPath))
    {
        Write-Host Item Found with $ProgramName in item starting with byte $key
            $bytRegKey[$([Convert]::ToInt32($key)+528)] = $setting
            Set-ItemProperty $($(Get-Item 'HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify').PSPath) -name IconStreams -value $bytRegKey
    }
}

Save it as a ps1 file using the name of your choice.

Open up the Group Policy Management MMC. Select your chosen Group Policy Object, right click and select Edit. In the editor, navigate to User Configuration > Windows Settings > Scripts > Logon and click "Display Properties". Go to the PowerShell tab and click View Files.

Copy the script you just made into the Explorer window that just opened and then close out of the window.

In the login script properties window, add a new PowerShell script, in the script name, enter the name of the script you used (example: NotifyIcon.ps1), and then in the parameters, enter the program name (case sensitive!) followed by the setting to use:

0 = only show notifications 1 = hide icon and notifications 2 = show icon and notifications <--- The one you need

Example, if you need the RealVNC server to always appear, you would enter:

winvnc4.exe 2

as the paramenters

You can find out the name of the executable in a couple different ways, such as opening a Run dialogue box and typing msconfig and looking at the startup programs, manually navigating to the installation directory C:\Program Files\{your program}, or trying to match the desired program by looking at the running processes in Task Manager. 9 times out of 10 this will result in success.

In order for this to work, the user must have previously run the application, and then properly logged out, so that explorer.exe gets a chance to write the updated notification area history to the Registry. On a subsequent login, the script should successfully locate the program in the history, and update its setting to always show.

You can also try running the script manually from a PowerShell prompt to debug, but you MUST kill explorer.exe (‘taskkill /f /im explorer.exe’) before running it, otherwise explorer won’t see your update, and will overwrite it when it does quit.

I take no credit for this process. I didn't write it, I just found it. Credit for the script goes to Micah Rowland. Credit for the GPO process goes to Geoff Kendal

Joshua Parnell

Posted 2011-08-02T13:41:51.390

Reputation: 108

It works well, but runs really slow: takes > 20 sec to complete on my reasonable fast PC. – Mozzis – 2016-03-28T22:04:14.617

I'm out of the office for a while, and by the time I get back I'll have forgotten about this. If you can @reply this comment late next week I'll be able to take a closer look and maybe switch the accepted answer. – Joel Coehoorn – 2013-09-05T15:40:40.503

Link-only answers are a no-no due to possible future link-rot. Please include pertinent information in your answer. We also don't care if you answered an old question, it's actually a GOOD thing, so please consider removing your "apology" and reasons for posting. :) – Ƭᴇcʜιᴇ007 – 2013-09-05T16:49:45.977

@techie007 Thanks, edited

@ Joel Coehoorn I'll post a sticky note to remind me :P – Joshua Parnell – 2013-09-05T19:31:10.943

@JoelCoehoorn Here's your @ reply. Sorry it took so long, plumb forgot about it. – Joshua Parnell – 2013-09-20T03:19:51.073

4

I don't know if you can set the cache order for icons considering it could constantly be changing if new programs were added, but you can set the notification to "Always show all icon and notifications on the taskbar".

To set this to be the default, go to this registry key:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer

Add the DWORD value "EnableAutoTray", double-click it, and set the hexadecimal value to "0".

I tested this and it worked.

Interesting note: I first tried to add it to this key:

HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer

I have always thought that was the default registry for new users, but it did not work. So I went looking and found this interesting article busting my long-held thoughts about that .DEFAULT key.

http://blogs.msdn.com/b/oldnewthing/archive/2007/03/02/1786493.aspx

Addition: The best I can tell is that the registry entries are here If you were going to try and set one icon the way you would if you opened up "Control Panel\All Control Panel Items\Notification Area Icons":

HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify

If you look at them, they are not very understandable, so I am not sure how well you would do editing them.

I suggest that you consider making a new user and its profile, set the "Control Panel\All Control Panel Items\Notification Area Icons" for that one icon (at least) to "Show Icon and Notifications".

Then reboot to release the profile, and log in as administrator. Copy that profile to the "C:\Users\Default" profile. You can do that either manually using Explorer, or the way we used to do it in "Control Panel\All Control Panel Items\System" "Advanced System Settings>Advanced>User Profiles>Copy to". It will be grayed out, but you can use the Windows Enabler to get around that.

KCotreau

Posted 2011-08-02T13:41:51.390

Reputation: 24 985

I'd rather not show all the icons, but I will if I must. – Joel Coehoorn – 2011-08-02T15:11:50.670

I am going to add to the answer. – KCotreau – 2011-08-02T15:49:26.567

I've seen the Windows Enabler and other copy profile solutions, but experimentation has shown that this really is broken for windows 7. It makes me sad :( – Joel Coehoorn – 2011-08-02T16:54:41.233

I agree Joel, WHY would they disable that function? I still have no idea other than people trying to copy it to the wrong place. – KCotreau – 2011-08-02T17:01:01.260

@KCotreau: It was on the Windows Deployment blogs. It has something to do with certain operations that happen only during the creation of the profile, ie "Preparing your desktop. . ." Frankly it sucks, but I can see why they are trying to move everyone away from this method. It's just simply unpredictable what the end results will be. – surfasb – 2011-08-02T17:22:37.463

1

#this will grab all the SID on current user and apply across all.
Function Enable-Notifications
{
    Param
        (
        [parameter(Mandatory=$false)][string]$cpuName
        )


        if (Test-Connection $cpuName -Quiet)    
        {
Try
                {
                    $serviceName = "Remote Registry"  
                    Get-Service -ComputerName $cpuName -Name $serviceName | Start-Service
                }
                Catch
                {
                    Write-Host "Possible Error restarting $serviceName on $cpuName" -ForegroundColor Red
                }
                Try
                {
                    $root = [Microsoft.Win32.RegistryHive]::Users
                    $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($root, $cpuName)

                    $users = $regKey.GetSubKeyNames() | where { $_.Length -gt 10 -and $_.EndsWith("_Classes") -eq $false }
                    foreach ($usersid in $users)
                    {
                        $key = "$usersid\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer"
                        $regKey = $regKey.OpenSubKey($key, $true)
                        $regKey.SetValue("EnableAutoTray", "0", 'DWORD')
                    }
                    $ActiveUser = ([Environment]::UserDomainName + "\" + [Environment]::UserName)
                    $Time = Get-Date -format "MM-dd-yyyy @ HH:mm"
                    $WriteOut = "$ActiveUser enabled Notifcations on $cpuName at $Time"
                    $WriteOut >> "c:\scripts\Notification-Update-Enable.csv"
                    Write-Host "Enable Notifications on $cpuName" -ForegroundColor Green
                }       
                Catch
                {
                    $errormsg = $cpuName + ” is down/not responding.”
                    Write-Host $errorMsg -ForegroundColor Red
                    $errormsg >> "c:\scripts\Notification-Update-Enable_Off.csv"
                }
}
        else
        {
            Write-Host "$cpuName is Offline. Try again later." -ForegroundColor Red
            $errormsg >> "c:\scripts\Notification-Update-Enable_Off.csv"
        }
}

paul

Posted 2011-08-02T13:41:51.390

Reputation: 11

FYI there's a code block format wrapper so you don't have to use <br> on every line. – Enigma – 2016-03-09T15:11:06.857

1

Run this as admin:

Set-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer EnableAutoTray 0

Notice the HKLM instead HKCU.

Verify effect with:

ps explorer | kill

It shows all icons for all profiles.

majkinetor

Posted 2011-08-02T13:41:51.390

Reputation: 510

0

it is now available in later versions group policy, see option B

All of these options are available in User Configuration\Administrative Templates\Start Menu and Taskbar

You can either:

A) Turn it off completely or turn it on completely ("hide the notification area," works for both XP and 7)

B) Have it show all, or continue to show the icons the user specifies ("turn off notification area cleanup," works for both XP and 7)

C) Disable only certain icons included in the default GPO, such as Action Center, Networking, Battery Meter, Volume. As far as I can tell, those are the only 4 Notification Area icons you can work with via the default 2008R2 GPO (and these only work for Vista and above or 7 and above).

technonath

Posted 2011-08-02T13:41:51.390

Reputation: 1

1So, then, what I asked about is not available via group policy, since I'm wanting to force a specific icon to always show, and that's not one of the GPO options described here. – Joel Coehoorn – 2014-10-21T13:25:38.433