locked
Click button using SendMessage [VB.NET] RRS feed

  • Question

  • hi guys..

    i need click on this button using SendMessage in VB.NET

    target and info from spy++

    i need click to button ( Uninstall )

    Thursday, June 8, 2017 7:42 AM

Answers

  • i wroted &Uninstall and Uninstall and nothing work :/

     Your code is wrong.  You are sending a BN_CLICKED message which is actually suppose to have a value of 245 which is a Button Notification message.  You want the BM_CLICK message instead,  which is a Button Message.  You are also trying to send that message to the dialog window`s handle.  You want to sent the BM_CLICK message to the button`s handle.  Try the below code and see if it works.

    Imports System.Runtime.InteropServices

    Public Class Form1
        Private Const BM_CLICK As Integer = &HF5
        Private Const WM_ACTIVATE As Integer = &H6
        Private Const WA_ACTIVE As Integer = &H1

        <DllImport("user32.dll", EntryPoint:="FindWindowExW")>
        Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
        End Function

        <DllImport("user32.dll", EntryPoint:="SendMessageW")>
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        End Function

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hWndAbout As IntPtr = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "#32770", "about notepad") 'use the dialog window's text in second parameter
            Label1.Text = hWndAbout.ToString  'Get handle fine!
            Dim hWndOkButton As IntPtr = FindWindowExW(hWndAbout, IntPtr.Zero, "button", "ok")
            Label2.Text = hWndOkButton.ToString 'Not get handle button just get 0
            SendMessageW(hWndOkButton, WM_ACTIVATE, New IntPtr(WA_ACTIVE), IntPtr.Zero)
            SendMessageW(hWndOkButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
        End Sub
    End Class



    If you say it can`t be done then i`ll try it

    • Marked as answer by Salar Music Friday, June 9, 2017 12:17 AM
    • Edited by IronRazerz Friday, June 9, 2017 12:21 AM
    Thursday, June 8, 2017 3:21 PM

All replies

  • Get the main window handle, then the button handle (with FindWindowEx() for example)

    then send WM_COMMAND with BN_CLICKED to the main window handle

    <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
    Public Const WM_COMMAND = &H111
    Public Const BN_CLICKED = 0


    Thursday, June 8, 2017 8:00 AM
  • can you explian more to mee how to use this functions??

    give me example

    Thursday, June 8, 2017 8:15 AM
  • Get the main window handle, then the button handle (with FindWindowEx() for example)

    then send WM_COMMAND with BN_CLICKED to the main window handle

    <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
    Public Const WM_COMMAND = &H111
    Public Const BN_CLICKED = 0


    i write:

    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
    
        Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
        ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
    
        <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("User32.dll")> _
        Public Shared Function FindWindow(ByVal className As String, ByVal caption As String) As IntPtr
        End Function
    
        Public Const WM_COMMAND = &H111
        Public Const BN_CLICKED = 0
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
    
            Dim MainWindowHandle As IntPtr = FindWindow(Nothing, "Example")
            Dim UninstallButtonHandle As IntPtr = FindWindowEx(MainWindowHandle, Nothing, "Example", Nothing)
            UninstallButtonHandle = FindWindowEx(UninstallButtonHandle, Nothing, "Button", Nothing)
    
        End Sub
    End Class
    
    

    true or false??

    how to use sendmessage??

    Thursday, June 8, 2017 8:18 AM
  • For example, to close the DialogBox "About" of Notepad, assuming it is opened.

    I hard-coded the title to test on my french OS (should be something like "About Notepad" in english...) :

    Dim hWndAbout As IntPtr = FindWindow("#32770", "À propos de : Bloc-notes")
    Dim hWndOkButton As IntPtr = FindWindowEx(hWndAbout, IntPtr.Zero, "Button", "Ok")
    SendMessage(hWndAbout, WM_COMMAND, MakeLong(GetDlgCtrlID(hWndOkButton), BN_CLICKED), hWndOkButton)
    
    <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        End Function
    
    Public Function MakeLong(lowPart As Short, highPart As Short) As Integer
        Return CInt(CUShort(lowPart) Or CUInt(highPart << 16))
    End Function
    
    <DllImport("user32")>
        Public Shared Function GetDlgCtrlID(hWnd As IntPtr) As Integer
        End Function


    • Edited by Castorix31 Thursday, June 8, 2017 8:47 AM
    Thursday, June 8, 2017 8:32 AM
  • For example, to close the DialogBox "About" of Notepad, assuming it is opened.

    I hard-coded the title to test on my french OS (should be something like "About Notepad" in english...) :

    Dim hWndAbout As IntPtr = FindWindow("#32770", "À propos de : Bloc-notes")
    Dim hWndOkButton As IntPtr = FindWindowEx(hWndAbout, IntPtr.Zero, "Button", "Ok")
    SendMessage(hWndAbout, WM_COMMAND, MakeLong(GetDlgCtrlID(hWndOkButton), BN_CLICKED), hWndOkButton)
    
    <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        End Function
    
    Public Function MakeLong(lowPart As Short, highPart As Short) As Integer
        Return CInt(CUShort(lowPart) Or CUInt(highPart << 16))
    End Function
    
    <DllImport("user32")>
        Public Shared Function GetDlgCtrlID(hWnd As IntPtr) As Integer
        End Function

    sorry not work in my projec

    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
    
        Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
        ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
    
        <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("User32.dll")> _
        Public Shared Function FindWindow(ByVal className As String, ByVal caption As String) As IntPtr
        End Function
    
        Public Function MakeLong(lowPart As Short, highPart As Short) As Integer
            Return CInt(CUShort(lowPart) Or CUInt(highPart << 16))
        End Function
    
        <DllImport("user32")>
        Public Shared Function GetDlgCtrlID(hWnd As IntPtr) As Integer
        End Function
    
        Public Const WM_COMMAND = &H111
        Public Const BN_CLICKED = 0
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            Dim hWndAbout As IntPtr = FindWindow(Nothing, "Example V4.1.1 Uninstall ")
            Dim hWndOkButton As IntPtr = FindWindowEx(hWndAbout, IntPtr.Zero, "Button", "Uninstall")
            SendMessage(hWndAbout, WM_COMMAND, MakeLong(GetDlgCtrlID(hWndOkButton), BN_CLICKED), hWndOkButton)
    
        End Sub
    End Class
    
    

    Thursday, June 8, 2017 8:45 AM
  • I do not own windows

    Why use

    FindWindowEx

    ??

    Thursday, June 8, 2017 8:48 AM
  • FindWindowEx() is used to find a direct child window

    From Spy++ for About Dialog Box of Notepad, "OK" button is a direct child :

    Thursday, June 8, 2017 8:55 AM
  • Why go to all this trouble when you can run a silent uninstall instead using a command line option?

    Paul ~~~~ Microsoft MVP (Visual Basic)

    Thursday, June 8, 2017 12:55 PM
  • FindWindowEx() is used to find a direct child window

    From Spy++ for About Dialog Box of Notepad, "OK" button is a direct child :

    please read my comment in codes

    Imports System.Runtime.InteropServices
    
    Public Class Form1
    
    
        Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, _
        ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
    
        <DllImport("user32", SetLastError:=True, CharSet:=CharSet.Auto)>
        Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("User32.dll")> _
        Public Shared Function FindWindow(ByVal className As String, ByVal caption As String) As IntPtr
        End Function
    
        Public Function MakeLong(lowPart As Short, highPart As Short) As Integer
            Return CInt(CUShort(lowPart) Or CUInt(highPart << 16))
        End Function
    
        <DllImport("user32")>
        Public Shared Function GetDlgCtrlID(hWnd As IntPtr) As Integer
        End Function
    
        Public Const WM_COMMAND = &H111
        Public Const BN_CLICKED = 0
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hWndAbout As IntPtr = FindWindow("#32770", Nothing)
            Label1.Text = hWndAbout  'Get handle fine!
            Dim hWndOkButton As IntPtr = FindWindowEx(hWndAbout, IntPtr.Zero, "Button", "Uninstall")
            Label2.Text = hWndOkButton 'Not get handle button just get 0
            SendMessage(hWndAbout, WM_COMMAND, MakeLong(GetDlgCtrlID(hWndOkButton), BN_CLICKED), hWndOkButton)
        End Sub
    End Class
    
    

    info from spy++

    Thursday, June 8, 2017 2:08 PM

  • info from spy++

    I see "&Uninstall" for button text (instead of "Uninstall")

    (but as Paul P Clement IV said, can't you do it by a command line ?)


    • Edited by Castorix31 Thursday, June 8, 2017 2:13 PM
    Thursday, June 8, 2017 2:13 PM

  • info from spy++

    I see "&Uninstall" for button text (instead of "Uninstall")

    (but as Paul P Clement IV said, can't you do it by a command line ?)


    i wroted &Uninstall and Uninstall and nothing work :/

    Thursday, June 8, 2017 2:36 PM
  • You can enumerate child windows to check them (displayed in Output window to test)

    Example with Notepad :

    Dim hWndNotepad As IntPtr = FindWindow("Notepad", Nothing) Dim hWndChildWindow As Integer = 0 If (hWndNotepad) Then Dim callback As EnumChildCallback = New EnumChildCallback(AddressOf EnumChildWindowsProc) EnumChildWindows(hWndNotepad, callback, hWndChildWindow) End If Public Function EnumChildWindowsProc(hWnd As IntPtr, ByRef lParam As Integer) As Boolean Dim sWindowClass As StringBuilder = New StringBuilder(128) GetClassName(hWnd, sWindowClass, 128) Dim sWindowText As String Dim hGlobal As IntPtr = Marshal.AllocHGlobal(260) Dim nNbChars As Integer = SendMessage(hWnd, WM_GETTEXT, 260, hGlobal) sWindowText = Marshal.PtrToStringUni(hGlobal) Marshal.FreeHGlobal(hGlobal) Console.WriteLine("Window : {0:X} - Class : {1} - Text : {2}", hWnd.ToString("x"), sWindowClass.ToString, sWindowText) Return True End Function Public Delegate Function EnumChildCallback(ByVal hwnd As Integer, ByRef lParam As Integer) As Boolean <DllImport("User32")> Public Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumChildCallback, ByRef lParam As Integer) As Boolean End Function <DllImport("User32")> Public Shared Function GetClassName(ByVal hWnd As IntPtr, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer End Function <DllImport("user32", CharSet:=CharSet.Auto)> Public Shared Function GetWindowText(hWnd As IntPtr, lpString As StringBuilder, nMaxCount As Integer) As Integer End Function

    Public Const WM_GETTEXT As Integer = &HD



    • Edited by Castorix31 Thursday, June 8, 2017 3:20 PM
    Thursday, June 8, 2017 3:19 PM
  • i wroted &Uninstall and Uninstall and nothing work :/

     Your code is wrong.  You are sending a BN_CLICKED message which is actually suppose to have a value of 245 which is a Button Notification message.  You want the BM_CLICK message instead,  which is a Button Message.  You are also trying to send that message to the dialog window`s handle.  You want to sent the BM_CLICK message to the button`s handle.  Try the below code and see if it works.

    Imports System.Runtime.InteropServices

    Public Class Form1
        Private Const BM_CLICK As Integer = &HF5
        Private Const WM_ACTIVATE As Integer = &H6
        Private Const WA_ACTIVE As Integer = &H1

        <DllImport("user32.dll", EntryPoint:="FindWindowExW")>
        Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
        End Function

        <DllImport("user32.dll", EntryPoint:="SendMessageW")>
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        End Function

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hWndAbout As IntPtr = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "#32770", "about notepad") 'use the dialog window's text in second parameter
            Label1.Text = hWndAbout.ToString  'Get handle fine!
            Dim hWndOkButton As IntPtr = FindWindowExW(hWndAbout, IntPtr.Zero, "button", "ok")
            Label2.Text = hWndOkButton.ToString 'Not get handle button just get 0
            SendMessageW(hWndOkButton, WM_ACTIVATE, New IntPtr(WA_ACTIVE), IntPtr.Zero)
            SendMessageW(hWndOkButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
        End Sub
    End Class



    If you say it can`t be done then i`ll try it

    • Marked as answer by Salar Music Friday, June 9, 2017 12:17 AM
    • Edited by IronRazerz Friday, June 9, 2017 12:21 AM
    Thursday, June 8, 2017 3:21 PM
  • 'some buttons seem to need to receive the message a second time, not sure why???
       

    If button is on a dialog type window MSDN says to activate the button first then click it. Sorry no link to MSDN but this is how I've done it for years...

    SendMessage(hWnd, WM_ACTIVATE, WA_ACTIVE, IntPtr.Zero)
    SendMessage(hWnd, BM_CLICK,IntPtr.Zero, IntPtr.Zero)


    • Edited by Edgemeal Thursday, June 8, 2017 9:56 PM
    Thursday, June 8, 2017 9:54 PM
  • SOLVED!

    Imports System.Runtime.InteropServices
    
    Public Class Form1
        Private Const BM_CLICK As Integer = &HF5
        Private Const WM_SETFOCUS As Integer = &H7
    
        <DllImport("user32.dll", EntryPoint:="FindWindowExW")>
        Private Shared Function FindWindowExW(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")>
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        End Function
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim hWndAbout As IntPtr = FindWindowExW(IntPtr.Zero, IntPtr.Zero, Nothing, "Example") 'use the dialog window's text in second parameter
            Label1.Text = hWndAbout.ToString  'Get handle fine!
            Dim hWndOkButton As IntPtr = FindWindowExW(hWndAbout, IntPtr.Zero, "Button", "&Uninstall")
            Label2.Text = hWndOkButton.ToString 'Not get handle button just get 0
            SendMessageW(hWndOkButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
            SendMessageW(hWndOkButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero) 'some buttons seem to need to receive the message a second time, not sure why???
        End Sub
    End Class

    Thursday, June 8, 2017 11:48 PM
  • SOLVED! ......

     Please check the code i posted in my last post,  i have updated it to activate the button by sending it a WM_ACTIVATE message first,  and then click the button with the BM_CLICK message as  Edgemeal has said.  It is written in the Remarks section of the msdn documents for the BM_CLICK message

     


    If you say it can`t be done then i`ll try it

    Friday, June 9, 2017 12:35 AM