Set tray icon to always show

2019-03-09 20:58发布

问题:

How I can I set a NotifyIcon to be always visible in the right tray: http://screensnapr.com/v/qKWHe2.png

because it shifts it over into the inactive icon window: http://screensnapr.com/v/jjtuK0.png

The issue is that the tray icon has a context menu that lets someone take a screen shot. So every time they take a screenshot, that inactive icon window is in the picture, blocking whatever is behind it like a photo bomber.

I know it is possible to do it through code because other applications such as comodo has done it without having me drag and drop the icon onto there. For pining a shortcut to the taskbar I learned that you set a shortcut in this folder:

C:\Users\Username\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

Is there something similar for the tray? Or is there an option I can use code wise.

回答1:

Not applicable by code, just instruct users to make it always show

http://blogs.msdn.com/b/oldnewthing/archive/2010/12/15/10105142.aspx

But you can manage to hack it by modifying a registry entry

HKEY_Current_User\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify

check this



回答2:

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

Not enough reputation to link to original authors, with the exception of the one at the top.



回答3:

Giving notification area icons "always visible" status is a choice the user makes through the taskbar properties dialog. This is a design decision made by the appropriate Windows team in order to put this choice at the user's discretion.

For this reason, there is no programmatic interface that allows you to make an icon always visible. There's even no interface to ask if your icon is visible or not.

In your shoes I 'd just set up a hotkey that allows the user to take screenshots without getting involved with the icon at all (all screen capture programs do this).

If the user really likes to right click before taking a screenshot, they can always change their preference through taskbar properties as mentioned above.



回答4:

Microsoft has explicitly taken the stance that this is a decision for the user and not one that can be made programmatically. Yes there are various utilities around that hack at the internals to achieve this, but there is no supported way to achieve what you desire.



回答5:

Using something like this script to enhance a software package so that with a simple checkbox the user can decide whether to pin the icon to the notification area (or not) without having to jump through the various hoops that Microsoft has chosen to put in the way seems like a fantastic idea in terms of accessibility.

Maybe if Microsoft had offered a right click pin/unpin option on the notification area icons (like the taskbar), or the ability for a program to easily offer such a feature we wouldn't be having this discussion.