題 始終為Windows 7中的所有配置文件顯示特定托盤圖標


我正在設置一台Windows 7機器,它將在公開場合閒置,並由很多人共享。我在所有用戶的開始菜單中添加了一個快捷方式,以運行位於系統托盤中的程序。我希望默認情況下該程序的托盤圖標始終可見,無論誰登錄。用戶可以在他們的個人資料中關閉它,如果他們真的想要,但我需要它至少開始設置為始終可見。我怎樣才能做到這一點?

我寧願不顯示所有的圖標,部分是出於同樣的原因,它們首先隱藏起來:我不想要雜亂。此外,由於這是一台公共計算機,還有另一個名為DeepFreeze的程序,它還有一個系統托盤圖標,我不希望該圖標一直顯示。


13
2017-08-02 13:41


起源


您是否可以通過其他機制顯示圖標/消息而不是系統托盤? - jalf


答案:


在堅果殼中,目前,你不能這樣做。

沒有組策略或首選項來設置它,它跟踪的方式使其特定於當前用戶和系統,使得“設置”在不同實例之間變化很大。

它們存儲在這裡(在註冊表中),如果你想檢查出來: 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上下文中使用它,如果您只希望某些用戶/組發生它。

看到 這裡 有關更多信息。


11
2017-08-02 14:59



我寧願不顯示所有的圖標,但如果必須,我會的。 - Joel Coehoorn


我在網上搜索,實際上是隨機發現的。

簡而言之,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 / im explorer.exe'),否則資源管理器將無法看到您的更新,並會覆蓋當它退出時它。

我不贊成這個過程。我沒有寫它,我發現它。該劇本的功勞歸功於 米卡羅蘭德。歸功於GPO流程 傑夫肯德爾


10
2017-09-05 14:44



我已經離開辦公室一段時間了,當我回來的時候,我已經忘記了這一點。如果你可以在下週晚些時候@reply這個評論,我將能夠仔細看看,也許可以切換接受的答案。 - Joel Coehoorn
由於可能的未來鏈接腐爛,僅鏈接答案是禁忌。請在答案中包含相關信息。我們也不在乎你是否回答了一個老問題,這實際上是一件好事,所以請考慮刪除你的“道歉”和發布原因。 :) - Ƭᴇcʜιᴇ007
@ techie007謝謝,編輯@ Joel Coehoorn我會發一張便條提醒我:P - Joshua Parnell
@JoelCoehoorn這是你的@回复。對不起,花了這麼長時間,鉛錘忘了它。 - Joshua Parnell
它運行良好,但運行速度非常慢:在合理的快速PC上完成需要> 20秒。 - Mozzis


我不知道你是否可以設置圖標的緩存順序,因為如果添加新程序它可能會不斷變化,但你可以將通知設置為“始終在任務欄上顯示所有圖標和通知”。

要將其設置為默認值,請轉到此註冊表項:

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啟動器 繞過那個。


4
2017-08-02 14:35



我寧願不顯示所有的圖標,但如果必須,我會的。 - Joel Coehoorn
我想補充一下答案。 - KCotreau
我已經看過Windows啟動器和其他復製配置文件解決方案,但實驗表明這對於Windows 7來說確實已經破了。這讓我很傷心:( - Joel Coehoorn
我同意喬爾,為什麼他們會禁用這個功能?我還是不知道除了人們試圖將它複製到錯誤的地方。 - KCotreau
@KCotreau:它出現在Windows部署博客上。它與僅在創建配置文件期間發生的某些操作有關,即“準備桌面......”。坦率地說,它很糟糕,但我可以看出為什麼他們試圖讓所有人遠離這種方法。這只是不可預知的最終結果。 - surfasb


以管理員身份運行:

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

請注意 HKLM 代替 HKCU

驗證效果:

ps explorer | kill

它顯示所有配置文件的所有圖標。


1
2018-05-15 12:07





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

1
2018-03-09 13:56



僅供參考,我們有一個代碼塊格式包裝器,因此您不必使用 <br> 在每一行。 - Enigma


它現在可在更高版本的組策略中使用,請參閱選項B.

所有這些選項都可用於 User Configuration\Administrative Templates\Start Menu and Taskbar

你可以:

A)完全關閉或完全打開(“隱藏通知區域”,適用於XP和7)

B)讓它顯示全部,或繼續顯示用戶指定的圖標(“關閉通知區域清理”,適用於XP和7)

C)僅禁用默認GPO中包含的某些圖標,例如Action Center,Networking,Battery Meter,Volume。據我所知,這些是您可以通過默認的2008R2 GPO使用的唯一4個通知區域圖標(這些僅適用於Vista及以上或7及以上版本)。


0
2017-10-21 10:27



那麼,我所詢問的內容是不可通過組策略獲得的,因為我想強制一個特定的圖標始終顯示,而這不是這裡描述的GPO選項之一。 - Joel Coehoorn