使特定托盘图标始终显示在Windows 7中的所有配置文件中


13

我正在设置一台Windows 7计算机,该计算机将在公开场合摆放,并被很多人共享。我向所有用户的开始菜单添加了一个快捷方式,以运行位于系统托盘中的程序。我希望该程序的托盘图标在默认情况下始终可见,无论是谁登录。用户如果愿意,可以在个人资料上将其关闭,但我至少需要将其设置为始终可见。我怎样才能做到这一点?

我宁愿不显示所有图标,部分原因是出于一开始它们被隐藏的相同原因:我不希望混乱。另外,由于这是一台公用计算机,因此还有另一个名为DeepFreeze的程序正在运行,该程序也具有系统任务栏图标,我不希望该图标始终显示。


您不能通过系统托盘以外的其他方式显示图标/消息吗?
jalf

Answers:


11

简而言之,当前您无法执行此操作。

没有组策略或首选项可以设置此设置,并且其跟踪方式使其特定于当前用户和系统,因此“设置”因实例而异。

如果要签出,它们存储在此处(在注册表中)HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\TrayNotify

这里

应用程序无法以编程方式始终在首次安装时或运行时的任何时候在系统托盘上始终显示自身的顶层。这是我们在Windows 7中进行的几项更改之一,目的是产生一个更干净,更安静的桌面,该桌面在用户的控制下,可以使用自己喜欢的应用程序和图标自定义顶层。

我们不允许用户进行程序化促销(暂时性或显示通知除外),从而使用户可以控制通知区域。假设机器足够安静,则当您首先使用Shell_NotifyIcon(NIM_ADD,...)添加图标时,它将在任务栏上显示45秒钟,然后移入溢出状态。如果用户升级图标,它将始终显示在任务栏上。如果用户将其降级,则该图标将永远不会在任务栏上显示。任何促销都需要用户发起。通过拖放和“通知区域图标”控制面板,我们在Windows 7中使此操作变得更加容易,并且在可用性研究中以及基于Beta反馈的过程中,我们发现用户毫无困难地发现如何自定义通知行为并宣传他们想要快速访问的图标。

关于您最简单的选择是为所有用户显示“所有通知区域”图标。这可以通过添加(简单)注册表项来完成:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer创建一个新的DWORD值EnableAutoTray并将其设置0为关闭通知区域的“自动隐藏”功能。

通过一些OU配置和脚本,如果您只希望某些用户/组发生这种情况,则也可以在HKCU上下文中使用它。

有关更多信息,请参见此处


我不想显示所有图标,但是如果需要的话,我会显示。
乔尔·科洪

10

我在网上搜索,实际上是随机发现的。

长话短说,是PowerShell(提供脚本)和GPO的组合。

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

长话短说,创建一个包含以下内容的PowerShell脚本:

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
    }
}

使用您选择的名称将其另存为ps1文件。

打开组策略管理MMC。选择您选择的组策略对象,右键单击并选择“编辑”。在编辑器中,导航到“用户配置”>“ Windows设置”>“脚本”>“登录”,然后单击“显示属性”。转到PowerShell选项卡,然后单击查看文件。

将您刚才创建的脚本复制到刚刚打开的资源管理器窗口中,然后关闭该窗口。

在登录脚本属性窗口中,添加一个新的PowerShell脚本,在脚本名称中,输入您使用的脚本的名称(例如:NotifyIcon.ps1),然后在参数中输入程序名称(区分大小写!),然后通过设置使用:

0 =仅显示通知1 =隐藏图标和通知2 =显示图标和通知<---您需要的一个

例如,如果您需要始终显示RealVNC服务器,请输入:

winvnc4.exe 2

作为参数

您可以通过几种不同的方式来找到可执行文件的名称,例如打开“运行”对话框并键入msconfig并查看启动程序,手动导航至安装目录C:\Program Files\{your program},或通过查看正在运行的程序来尝试匹配所需的程序。任务管理器中的进程。10次​​中有9次成功。

为了使其正常工作,用户必须事先运行过该应用程序,然后正确注销,以便explorer.exe有机会将更新的通知区域历史记录写入注册表。后续登录时,脚本应成功在历史记录中找到该程序,并将其设置更新为始终显示。

您也可以尝试从PowerShell提示符手动运行脚本进行调试,但是必须在运行脚本之前先杀死explorer.exe('taskkill / f /imexplorer.exe'),否则Explorer将看不到您的更新,并且将覆盖它确实退出时。

我对此过程不屑一顾。我没有写,只是找到了。该剧本的荣誉归功于Micah Rowland。GPO流程的功劳归功于Geoff Kendal


我不在办公室了一段时间,等我回来的时候,我已经忘了这个。如果您可以在下周晚些时候回复此评论,则可以仔细查看,甚至可以切换接受的答案。
Joel Coehoorn 2013年

仅链接的答案是不可以,因为将来可能会发生链接故障。请在答案中包括相关信息。我们也不在乎您是否回答了一个老问题,这实际上是一件好事,因此请考虑删除您的“道歉”和发布原因。:)
Ƭᴇcʜιᴇ007

@ techie007谢谢,编辑@ Joel Coehoorn我会贴一个便签提醒我:P
Joshua Parnell 2013年

@JoelCoehoorn这是您的@回复。抱歉,花了这么长时间,他完全忘记了。
约书亚·帕奈尔

它运行良好,但运行速度非常慢:在我合理的快速PC上需要20秒钟以上才能完成。
Mozzis

4

我不知道您是否可以设置图标的缓存顺序,因为如果添加了新程序,它可能会不断变化,但是您可以将通知设置为“始终在任务栏上显示所有图标和通知”。

要将其设置为默认值,请转到以下注册表项:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer

添加DWORD值“ EnableAutoTray”,双击它,并将十六进制值设置为“ 0”。

我对此进行了测试,并成功了。

有趣的注释:我首先尝试将其添加到此密钥:

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

我一直认为这是新用户的默认注册表,但是它没有用。因此,我继续寻找并发现了这篇有趣的文章,破坏了我对.DEFAULT密钥的长期保留。

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

另外:我能说的最好的是注册表项在这里,如果您要尝试设置一个图标,就像打开“ Control Panel\All Control Panel Items\Notification Area Icons”时那样:

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

如果您看一下它们,它们并不是很容易理解,所以我不确定您对它们的编辑程度如何。

我建议您考虑建立一个新用户及其配置文件,将该图标的“控制面板\所有控制面板项目\通知区域图标”(至少)设置为“显示图标和通知”。

然后重新启动以释放配置文件,并以管理员身份登录。将该个人资料复制到“ C:\Users\Default”个人资料。您可以使用资源管理器手动执行此操作,也可以使用我们以前在“ Control Panel\All Control Panel Items\System“”中执行此操作的方式来执行Advanced System Settings>Advanced>User Profiles>Copy to。它会变灰,但是您可以使用Windows启动器来解决。


我不想显示所有图标,但是如果需要的话,我会显示。
Joel Coehoorn

我将添加到答案。
KCotreau

我已经看到了Windows的启动和其他配置文件复制解决方案,但实验显示,这确实是打破了Windows 7的让我伤心:(
乔尔Coehoorn

我同意Joel,为什么他们会禁用该功能?除了人们试图将其复制到错误的地方外,我仍然没有其他想法。
KCotreau

@KCotreau:在Windows部署博客中。它与仅在创建配置文件期间发生的某些操作有关,即“准备桌面...”。坦白说,它很烂,但是我可以理解为什么他们试图让所有人都摆脱这种方法。最终结果将是完全无法预测的。
surfasb

1

以管理员身份运行此命令:

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

注意HKLM而不是HKCU

验证效果:

ps explorer | kill

它显示所有配置文件的所有图标。


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"
        }
}

仅供参考,有一个代码块格式包装程序,因此您不必<br>在每一行上都使用。

0

现在在更高版本的组策略中可用,请参阅选项B

所有这些选项都可以在 User Configuration\Administrative Templates\Start Menu and Taskbar

您可以:

A)将其完全关闭或完全打开(“隐藏通知区域,对于XP和7均适用。)

B)全部显示,或继续显示用户指定的图标(“关闭通知区域清理, ”适用于XP和7。C)

仅禁用默认GPO中包含的某些图标,例如“操作中心”,“网络”,“电池电量计”,“音量”。据我所知,这些是您可以通过默认的2008R2 GPO使用的仅有的4个通知区域图标(这些仅适用于Vista或更高版本或7或更高版本)。


1
因此,我要询问的内容无法通过组策略获得,因为我想强制始终显示特定的图标,而这不是此处所述的GPO选项之一。
Joel Coehoorn 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.