Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 系统存取_C#_.net - Fatal编程技术网

C# 系统存取

C# 系统存取,c#,.net,C#,.net,有没有办法(用C#)访问systray? 我不是说制作通知图标。 我想遍历托盘中的项目(我想通过流程进行猜测,但我不知道如何确定托盘中的实际内容和流程),并在我自己的ui中用图标表示项目。Mathias Rauen的madCollection(适用于Delphi而非c#)可以列出 还有一个命令行工具: 我还用Delphi(不是Delphi.NET)编写(不是发布)了我自己的程序,没有使用madCollection,它显示托盘图标、进程名称、工具提示和其他信息,但并不完美。有几个图标它不能显示(即

有没有办法(用C#)访问systray? 我不是说制作通知图标。
我想遍历托盘中的项目(我想通过流程进行猜测,但我不知道如何确定托盘中的实际内容和流程),并在我自己的ui中用图标表示项目。

Mathias Rauen的madCollection(适用于Delphi而非c#)可以列出

还有一个命令行工具:


我还用Delphi(不是Delphi.NET)编写(不是发布)了我自己的程序,没有使用madCollection,它显示托盘图标、进程名称、工具提示和其他信息,但并不完美。有几个图标它不能显示(即使它列出了其他信息),并且在Windows9x下它不能显示任何图标。我还没有在Vista下测试过它。

你觉得Win32 interop怎么样?我发现这可能对你有用。(事实上,这看起来是一个有趣的问题,所以我可能会尝试自己解决它,而不是现在)

神奇的是,他获得了系统托盘窗口的手柄:

NotifyWnd = FindWindowEx(SysTray, 0, "TrayNotifyWnd", 0);
然后他在信息泵上设置了一个钩子:

hHook=SetWindowsHookEx(WH_CALLWNDPROC,HOOKPROC(MsgProc),
         hInstance,dwExplorerThreadId);
然后,在消息pump hook回调期间,他获得了对有关窗口的一些指针数据的引用:

TWDataT* twd=(TWDataT*)GetWindowLong(NotifyWnd,0);
神秘的是他的循环:

      pTWIconDataT p=COMCTL32_332(twd->iconsInfo,i);
COMCTL32_332是用GetProcAddress定义的,它指向COMCTL32.dll的第332个序号——根据我在Dependency Viewer中的检查,也就是说,它从动态指针数组中获取数据。我不熟悉那里的幕后情况,但这似乎不是完全不可能的


我将自己玩一玩,但希望这是一个让你开始的好地方。:)

在Windows 2000中,系统托盘图标位于普通工具栏控件(窗口类“ToolbarWindow32”)中,该控件是“TrayNotifyWnd”窗口的子窗口,因此您可以向其发送工具栏消息,例如
TB\u BUTTONCOUNT
TB\u GETBUTTON

不过,您需要小心:诸如TB_GETBUTTON之类的消息需要指向用于存储结果的缓冲区的指针,需要该缓冲区位于SysTray进程本身中。这要求您拥有正确的权限,并且使用
VirtualAllocEx
分配内存


我还没有在XP或Vista上试用过。我想事情已经改变了。

在Windows 2000/Xp中实现它是完全可能的。 不幸的是,在Windows7中,这似乎不再可行

诀窍很简单:您必须找到托盘窗口句柄:

        static IntPtr GetSystemTrayHandle()
    {
        IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
        if (hWndTray != IntPtr.Zero)
        {
            hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "TrayNotifyWnd", null);
            if (hWndTray != IntPtr.Zero)
            {
                hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "SysPager", null);
                if (hWndTray != IntPtr.Zero)
                {
                    hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "ToolbarWindow32", null);
                    return hWndTray;
                }
            }
        }

        return IntPtr.Zero;
    }
由于此窗口是ToolbarWindow32,因此必须使用WinAPI枚举整个按钮。唯一的问题是,用于此操作的所有结构都应该在目标进程地址空间中分配,因此您必须使用如下内容:

    private static unsafe bool GetTBButton(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
    {
        // One page
        const int BUFFER_SIZE = 0x1000;

        byte[] localBuffer = new byte[BUFFER_SIZE];

        UInt32 processId = 0;
        UInt32 threadId = User32.GetWindowThreadProcessId(hToolbar, out processId);

        IntPtr hProcess = Kernel32.OpenProcess(ProcessRights.ALL_ACCESS, false, processId);
        if (hProcess == IntPtr.Zero) { Debug.Assert(false); return false; }

        IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
            hProcess,
            IntPtr.Zero,
            new UIntPtr(BUFFER_SIZE),
            MemAllocationType.COMMIT,
            MemoryProtection.PAGE_READWRITE);

        if (ipRemoteBuffer == IntPtr.Zero) { Debug.Assert(false); return false; }

        // TBButton
        fixed (TBBUTTON* pTBButton = &tbButton)
        {
            IntPtr ipTBButton = new IntPtr(pTBButton);

            int b = (int)User32.SendMessage(hToolbar, TB.GETBUTTON, (IntPtr)i, ipRemoteBuffer);
            if (b == 0) { Debug.Assert(false); return false; }

            // this is fixed
            Int32 dwBytesRead = 0;
            IntPtr ipBytesRead = new IntPtr(&dwBytesRead);

            bool b2 = Kernel32.ReadProcessMemory(
                hProcess,
                ipRemoteBuffer,
                ipTBButton,
                new UIntPtr((uint)sizeof(TBBUTTON)),
                ipBytesRead);

            if (!b2) { Debug.Assert(false); return false; }
        }

        // button text
        fixed (byte* pLocalBuffer = localBuffer)
        {
            IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);

            int chars = (int)User32.SendMessage(hToolbar, TB.GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);
            if (chars == -1) { Debug.Assert(false); return false; }

            // this is fixed
            Int32 dwBytesRead = 0;
            IntPtr ipBytesRead = new IntPtr(&dwBytesRead);

            bool b4 = Kernel32.ReadProcessMemory(
                hProcess,
                ipRemoteBuffer,
                ipLocalBuffer,
                new UIntPtr(BUFFER_SIZE),
                ipBytesRead);

            if (!b4) { Debug.Assert(false); return false; }

            text = Marshal.PtrToStringUni(ipLocalBuffer, chars);

            if (text == " ") text = String.Empty;
        }
不幸的是,在Windows 7中,tbButton.dwData等于0,因此您无法找到NotifyIcon与目标进程之间的任何关联