2011-08-23 10 views
5

Quiero escribir el marco de automatización para la aplicación .NET. Para iniciar el usuario de la aplicación, haga clic con el botón derecho en el icono de la bandeja del sistema y seleccione la opción del menú contextual. He hecho algunas Resaerch y se encontró única manera cómo saber mensaje emergente del icono en la bandeja .:Cómo automatizar el clic derecho en el icono en la bandeja del sistema usando C#

[DllImport("user32.dll", SetLastError = true)] 
    static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName); 

    [DllImport("user32.dll", SetLastError = true)] 
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

    [DllImport("user32.dll", SetLastError = true)] 
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); 


    [DllImport("kernel32.dll")] 
    static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); 

    [Flags] 
    enum ProcessAccessFlags : uint 
    { 
     All = 0x001F0FFF, 
     Terminate = 0x00000001, 
     CreateThread = 0x00000002, 
     VMOperation = 0x00000008, 
     VMRead = 0x00000010, 
     VMWrite = 0x00000020, 
     DupHandle = 0x00000040, 
     SetInformation = 0x00000200, 
     QueryInformation = 0x00000400, 
     Synchronize = 0x00100000 
    } 


    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
    static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, FreeType dwFreeType); 

    [Flags] 
    public enum FreeType 
    { 
     Decommit = 0x4000, 
     Release = 0x8000, 
    } 

    const uint TB_GETBUTTON = 1047; 
    const uint TB_GETBUTTONTEXTW = 1099; 
    const uint TB_BUTTONCOUNT = 1048; 
    const uint TB_PRESSBUTTON = 1027; 
    const uint TB_HIDEBUTTON = 1028; 
    const uint VM_COMMAND = 273; 
    const uint WM_RBUTTONDOWN = 0x204; 
    const uint WM_RBUTTONUP = 0x205; 
    const uint MK_RBUTTON = 2; 
    const uint WM_COMMAND = 0x0111; 
    const uint BM_CLICK = 245; 
    const uint TB_HIGHLIGHTBUTTON = 0x0407; 


    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, 
     uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); 

    [DllImport("user32.dll", EntryPoint = "PostMessage")] 
    public static extern int PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 


    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint dwSize, out IntPtr lpNumberOfBytesRead); 

    [Flags] 
    public enum AllocationType 
    { 
     Commit = 0x1000, 
     Reserve = 0x2000, 
     Decommit = 0x4000, 
     Release = 0x8000, 
     Reset = 0x80000, 
     Physical = 0x400000, 
     TopDown = 0x100000, 
     WriteWatch = 0x200000, 
     LargePages = 0x20000000 
    } 

    [Flags] 
    public enum MemoryProtection 
    { 
     Execute = 0x10, 
     ExecuteRead = 0x20, 
     ExecuteReadWrite = 0x40, 
     ExecuteWriteCopy = 0x80, 
     NoAccess = 0x01, 
     ReadOnly = 0x02, 
     ReadWrite = 0x04, 
     WriteCopy = 0x08, 
     GuardModifierflag = 0x100, 
     NoCacheModifierflag = 0x200, 
     WriteCombineModifierflag = 0x400 
    } 


    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool CloseHandle(IntPtr hObject); 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct TBBUTTON 
    { 
     public Int32 iBitmap; 
     public Int32 idCommand; 
     public byte fsState; 
     public byte fsStyle; 
     public byte bReserved1; 
     public byte bReserved2; 
     public UInt32 dwData; 
     public IntPtr iString; 
    } 

    [DllImport("user32.dll")] 
    private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 


    //getting systemtray icon 
    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; 
    } 

    public static List<string> texts = new List<string>(); 

    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 = GetWindowThreadProcessId(hToolbar, out processId); 

     IntPtr hProcess = OpenProcess(ProcessAccessFlags.All, false, (int)processId); 
     if (hProcess == IntPtr.Zero) { Debug.Assert(false); return false; } 

     IntPtr ipRemoteBuffer = VirtualAllocEx(
      hProcess, 
      IntPtr.Zero, 
      (uint)new UIntPtr(BUFFER_SIZE), 
      AllocationType.Commit, 
      MemoryProtection.ReadWrite); 

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

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

      int b = (int)SendMessage(hToolbar, TB_GETBUTTON, (IntPtr)i, ipRemoteBuffer); 
      // SendMessage(hToolbar, VM_COMMAND, (IntPtr)tbButton.idCommand, ipRemoteBuffer); 


      if (b == 0) { Debug.Assert(false); return false; } 

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

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

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

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

      int chars = (int)SendMessage(hToolbar, TB_GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer); 

      //SendMessage(hToolbar, BM_CLICK, (IntPtr)tbButton.idCommand, IntPtr.Zero); 

      // int getmes = PostMessage(hToolbar, TB_HIDEBUTTON, (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 = ReadProcessMemory(
       hProcess, 
       ipRemoteBuffer, 
       ipLocalBuffer, 
       (uint)new UIntPtr(BUFFER_SIZE), 
       out ipBytesRead); 

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

      text = Marshal.PtrToStringUni(ipLocalBuffer, chars); 

      if (text.Contains("Pen")) 
      { 
       int buttonid = tbButton.idCommand; 
       SendMessage(hToolbar, TB_HIGHLIGHTBUTTON, (IntPtr)tbButton.idCommand, IntPtr.Zero); 
      } 
      texts.Add(text); 

      if (text == " ") text = String.Empty; 
     } 

     VirtualFreeEx(
      hProcess, 
      ipRemoteBuffer, 
      (int)UIntPtr.Zero, 
      FreeType.Release); 

     CloseHandle(hProcess); 

     return true; 
    } 



    static void Main(string[] args) 
    { 

     IntPtr _ToolbarWindowHandle = GetSystemTrayHandle(); 

     UInt32 count = (uint)SendMessage(_ToolbarWindowHandle, TB_BUTTONCOUNT, IntPtr.Zero, IntPtr.Zero); 

     for (int i = 0; i < count; i++) 
     { 
      TBBUTTON tbButton = new TBBUTTON(); 
      string text = String.Empty; 
      IntPtr ipWindowHandle = IntPtr.Zero; 

      bool b = GetTBButton(_ToolbarWindowHandle, i, ref tbButton, ref text, ref ipWindowHandle); 

     } 

     foreach (var item in texts) 
     { 
      Console.WriteLine(item); 
     } 
    } 
} 

¿Hay alguna forma de hacer clic derecho onsystem icono de la bandeja con C#? Estaría agradecido por las respuestas .......

Respuesta

3

No hay una forma programática de acceder a los iconos de la bandeja de otros programas (fuente: Raymond Chen). Todo lo que intentes no es más que un truco que puede romperse y fallar.

Trate de encontrar una manera que no implique tener que automatizar los clics con el botón derecho en los iconos de la bandeja. Tal vez el programa en cuestión se pueda controlar mediante alguna API o mediante parámetros de línea de comando.

+0

especialmente porque la bandeja no se actualiza visualmente cualquiera que sea. – kenny

+0

y de hecho si en Windows 7 el usuario ha personalizado el área de notificación para no mostrar el icono de esta aplicación en absoluto ... – AakashM

+0

Este marco de automatización se ejecutará y quiero probar escenarios con right-clik en la bandeja de iconos mientras el usuario realiza. Pensé que usando WINAPI32 podría ser posible en C#. –

Cuestiones relacionadas