Modify Windows 7 Notification Area

  • UPDATE:
  • Please dont use this version anymore cause its outdated, please follow the link for the new Version:
    https://hianz.wordpress.com/2013/09/03/new-windows-tray-notification-manager-is-here/


    I recoded / updated the example of http://deployment.xtremeconsulting.com/2011/07/08/windows-7-notification-area-automation-falling-back-down-the-binary-registry-rabbit-hole/ in .NET. I used the same logics but with a different language. Also its faster in searching for the Program in the REG_BINARY data of the registry:

     

    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Win32;
    using System.Collections;
    using System.Diagnostics;
    class Program
        {
            static void Main(string[] args)
            {
                Program p1 = new Program();
    
                string prName = null;
                RegistryKey myKey = Registry.CurrentUser.OpenSubKey("Software\\Classes\\Local Settings\\Software\\Microsoft\\Windows\\CurrentVersion\\TrayNotify", true);
                byte[] all = (byte[])myKey.GetValue("IconStreams");
                byte[] allwithoutheader = new byte[all.Length - 20];
                byte[] header = new byte[20];
    
                //Parse Header
                //------------------------
                for (int i = 0; i < all.Length; i++)
                {
                    if (i <= 19)
                    {
                        header[i] = all[i];
                    }
                    else
                    {
                        allwithoutheader[i - 20] = all[i];
                    }
                }
                //------------------------
                ArrayList blocklist = p1.storeBlocks(allwithoutheader);
                Console.WriteLine("Name(or part) of program:");
                prName = Console.ReadLine();
    
                string alldataString = null;
                bool found = false;
                int value = 0;
                int blocknumber = 0;
    
                for (int i = 0; i < blocklist.Count; i++)
                {
                    for (int j = 0; j < 1639; j++)
                    {
                        if (j < 528)
                        {
                            alldataString += System.Convert.ToChar(((List<byte>)(blocklist[i]))[j]);
                            if (j == 526)
                            {
                                string transformed = p1.Transform(alldataString);
                                string trimmed = System.Text.RegularExpressions.Regex.Replace(transformed, "\0+", "");
                                if (trimmed.Contains(prName))
                                {
                                    alldataString = null;
                                    Console.WriteLine("\n===================\n"+prName+" block found!"); //Block in ArrayList
                                    Console.WriteLine("current setting --> " + ((List<byte>)(blocklist[i]))[528]);
                                    Console.WriteLine("===================\nsettings: \n2 = show icon and notifications, \n1 = hide icon and notifications, \n0 = only show notifications\n===================");
                                    blocknumber = i;
                                    found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
    
                if (found == false)
                {
                    Console.WriteLine("Nothing found");
                    Console.ReadLine();
                    Environment.Exit(1);
                }
    
                Console.WriteLine("new setting:");
                value = Convert.ToInt32(Console.ReadLine());
                ((List<byte>)(blocklist[blocknumber]))[528] = (byte)(value);
    
                byte[] alloriginal = p1.getOriginalFormat(blocklist, allwithoutheader.Length);
                byte[] combined = p1.Combine(header, alloriginal);
    
                myKey.SetValue("IconStreams", combined);
                Console.WriteLine("Successfully wrote to Registry, please restart explorer.exe");
    
    
                Process[] pp = Process.GetProcessesByName("explorer");
                foreach (Process p in pp)
                {
                   
                    p.Kill();
                }
                Process.Start("explorer.exe");
            }
    
            private byte[] Combine(byte[] first, byte[] second)
            {
                byte[] ret = new byte[first.Length + second.Length];
                Buffer.BlockCopy(first, 0, ret, 0, first.Length);
                Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
                return ret;
            }
    
            private ArrayList storeBlocks(byte[] all)
            {
                ArrayList main = new ArrayList();
                List<byte> bytelist = new List<byte>();
    
                int help = 1639;
                int j = 0;
                for (int i = 0; i < all.Length; i++)
                {
                    bytelist.Add(all[i]);
                    if (i == help)
                    {
                        main.Add(bytelist);
                        bytelist = new List<byte>();
                        help = help + 1640;
                    }
                }
                return main;
            }
    
            private byte[] getOriginalFormat(ArrayList list, int bufferSize)
            {
                int help = 0;
                byte[] original = new byte[bufferSize];
                for (int i = 0; i < list.Count; i++)
                {
                    for (int j = 0; j < (((List<byte>)(list[i])).Count); j++)
                    {
    
                        original[help] = (((List<byte>)(list[i]))[j]);
                        help++;
                    }
                }
                return original;
            }
            private string Transform(string value)
            {
                char[] array = value.ToCharArray();
                for (int i = 0; i < array.Length; i++)
                {
                    int number = (int)array[i];
    
                    if (number >= 'a' && number <= 'z')
                    {
                        if (number > 'm')
                        {
                            number -= 13;
                        }
                        else
                        {
                            number += 13;
                        }
                    }
                    else if (number >= 'A' && number <= 'Z')
                    {
                        if (number > 'M')
                        {
                            number -= 13;
                        }
                        else
                        {
                            number += 13;
                        }
                    }
                    array[i] = (char)number;
                }
                return new string(array);
            }
        }<!--more-->
    
    Advertisements

    51 thoughts on “Modify Windows 7 Notification Area

    1. Hi there, great job with this wee program! I have made a small modification of your code so that the program will accept arguments. It is going to prove very useful …

    2. is it posible to hide icon from system tray ? options 0,1,2 already exists in windows system tray manager , how one can hide completely an icon ( an icon of a running program ) from system tray ?? is there a way to manually edit the registry if needed … ?

    3. I mean , a new “option 3” to completely delete the registry would work ( delete the icon without killing the running process )

    4. How difficult would it be to output all of the “Path to executable”s referenced in the PowerShell example webpage? This would be a huge help to understanding what needs to be disabled when automated.

    5. I can upload an exe somewhere after the New Year. I seem to recall that the original program will use the full program name, but it has to be case sensitive so for uTorrent you would need the capital T. I think that’s right, but can’t check till I am back at work.

      • Dear Andrew:I tested your program ,and it works great in win7.
        But , it is not working in windows 8
        Can you provide any suggestion?
        Thanks for your hard working

        • Hi milua, I have just tested in Windows 8 and it worked fine for me. What is the executable you are trying to change the notification settings for? In Task Manager, find your app then right-click > properties. Remember the program is case-sensitive.

        • Andrew, thx for your reply
          I test your program again, and I found the result.
          Because the process is opened as System account ,
          so it can’t work in win8 (process nothing found)

          ps: you can try psexec tool ,
          PsExec.exe -i -s cmd.exe —> open cmd.exe as system account

        • Hi Milua, what application/process is it? So the process shows up as “System” in task manager? And the icon in the system tray is running as System?

        • Hi Andrew, thx for your reply
          Firstly,the application is developed by myself .
          Secondly, that’s right, the process shows up as “System” in task manager and the icon in the system tray is running as system…. ( the pstool can run an application as system )
          Can you provide any suggestion? Thx

    6. Great Job! Works good! But is it difficult to add a parameter to skip the explorer restart? So the user will not interupt in his work and the settings will be active after a restart. Possible?

    7. If we have several icons with the same name like Outlook icon and Outlook new mail icon and notification, how to change both, instead of one of them with app.exe?

    8. great job andrew, much appreciated. Looking to use this to enable our kaseya agent tray icon to allow easy helpdesk ticket creations. Just to reask what mike said, is it possible to script without a restart of explorer? or is that required to work?

      Thanks again.
      Dan

    9. Thats ideal in my situation as our endpoints get restarted everynight and wake on lan wakes them up in the morning. If this script maybe had a final option 4 to allow the restart to happen at a later date that would great!.

      Dan

    10. Could easily incorporate the option to not restart. Will look at it when I am not too busy, would take a couple of hours to make the change and test.

    11. Hello thanks for wour work it’s very usefull

      I use the script in Logon User GPO like this

      SetTrayIconState.exe ccSvcHst.exe 2 /s

      But the problem is that explorer don’t load and users get a black screen

      We have to go in task manager and start explorer.exe manually

      It seem to do this only on 64 Bit Workstation

      Anyone have this problem ?

      • I have the same Problem on Win7 x64. I would like to have the .exe without restart automaticlly the explorer. But I can`t compile it. I would like to use it in a batch script in FOR – Loop and restart the explorer in the script.

    12. I’m trying to find the process for the Network icon with no luck! I want to hide that icon as all our computers are VM’s so my users will never need to see that icon. Anyone know how I can do this?

    13. I just add the Tools in Windows Logonscript.It is very usefull. I build a batch where some Tasks shown, but on every call the explorer restarts. Is there a possibility not automaticly restart the explorer.exe and I restarts after end of the batch manually ?

    14. Reposting here to get advice from fellow members, who might have faced this issue.

      From what I have understood, we need atleast a reboot after application (which needs to be displayed in systray). So that explorer.exe writes the required block in registry and on subsequent launch of application we can change the value from 0->2 and restart explorer.exe to display our application permanently in systray.

      Is it possible to avoid reboot?
      I used regmon to see that Dropbox also modifies same registry key and restarts explorer.exe.
      Only difference is that dropbox’s icon comes in systray as soon as explorer.exe restarts. It does not need a system restart/logoff.

      Any solution to avoid system reboot/logoff?

      • You dont need a system reboot / logoff:

        The IconStreams registry value is read into memory by Explorer.exe when explorer loads and all changes to the notification area are stored in memory, then written to the registry on shutdown. This means that if we run our script, not only will we see no results right away, those results will be overwritten with the current settings when we restart the computer. Not good. It’s a simple fix though. We launch our script from a batch file and we execute taskkill /im explorer.exe /f then we execute our script, then we restart explorer.exe. – Micah Rowland

    15. Unfortunately, this is not happening with me.
      1. I installed a new application which goes to systray
      2. taskkill /im explorer.exe /f
      3. Executed your code to toggle 528th byte from 0 to 2 (but it could not find the presence of newly installed program in registry and exited out).
      4. Restarted explorer.exe
      5. Executed your code to toggle 528th byte from 0 to 2 (still could not find the presence of newly installed program in registry and exited out).
      6. Restarted machine.
      7.Executed your code to toggle 528th byte from 0 to 2 (This time entry was found and byte’s value was toggled).
      8. Restarted explorer.exe and application is permanently visible in systray.

      For some reasons, my program is not able to find it’s entry in TrayNotify->IconStreams before a system reboot.

      Any pointers???

      • I commented further up: “I checked the program and it does take the name of the exe as shown in TaskManager, but it does have to be case-sensitive, so SkyDrive must be entered as “SkyDrive””

        What is the name of your exe? Are you entering it with the same case? Can I install your app and test it?

    16. Has anyone else had a problem with the latest compiled version crashing when running using a user account that did not have administrator rights?

      • This is the error I get when I try to run from a Windows 8 Enterprise computer using an account that is not an administrator:

        Unhandled Exception: System.NullReferenceException: Object reference not set to
        an instance of an object.
        at Program.Main(String[] args)

        If I make the same user an administrator, it runs without issue. If I try to use the runas command, it also fails.

      • I found the error above is not due to the admin rights. I thought it may be UAC. I tweaked the UAC settings and found it started to work. Then I set the UAC settings back to the max and it is still working, so not sure what the issue is\was.

      • And my final post, seems my corporate image needs another reboot after the user logs in. When I did that the script worked. Did not need to adjust permissions or UAC.

    17. I have been trying to find a way to hide the “Action Center” icon on new Win 7 installs. I don’t want to disable Action Center, and I know of the registry steps needed to do this, I just want to hide it. However I can’t make it happen with this program. It can’t find Action Center, as it’s a svchost.exe process. Any tips on what I can do here?

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s