2011-08-23 3 views
5

Chcę napisać strukturę automatyzacji dla aplikacji .NET. Aby uruchomić aplikację, należy kliknąć prawym przyciskiem myszy ikonę na pasku zadań i wybrać opcję z menu kontekstowego. Zrobiłem kilka resaerch i znaleźć tylko sposób jak poznać podpowiedzi z ikoną w zasobniku .:Jak zautomatyzować kliknięcie prawym przyciskiem myszy ikony w zasobniku systemowym przy użyciu 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); 
     } 
    } 
} 

Czy istnieje jakiś sposób, aby kliknąć prawym przyciskiem myszy ikonę na pasku onsystem przy użyciu C#? Byłbym wdzięczny za odpowiedzi .......

Odpowiedz

3

Nie ma programowego sposobu na dostęp do ikon w zasobniku innych programów (źródło: Raymond Chen). Wszystko, co wypróbujesz, jest niczym innym, jak włamaniem, które może się zepsuć i zawieść.

Spróbuj znaleźć sposób, który nie wymaga zautomatyzowania kliknięć prawym przyciskiem myszy na ikonach zasobnika. Może dany program może być kontrolowany za pomocą jakiegoś interfejsu API lub za pomocą parametrów wiersza poleceń.

+0

, zwłaszcza, że ​​taca nie odświeża się wizualnie odkurzacza. – kenny

+0

i rzeczywiście, jeśli w systemie Windows 7 użytkownik dostosował obszar powiadomień, aby w ogóle nie wyświetlał ikony tej aplikacji ... – AakashM

+0

To środowisko automatyzacji, które uruchomię, i chcę przetestować scenariusze z prawy kliknięciem na pasku zadań, gdy użytkownik wykonuje. Pomyślałem, że używając WINAPI32 może to być możliwe w C#. –