4

How can i send middle mouse click with power shell scripts? I want something like this:

Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.SendKeys]::SendWait('{MButton}')
Mahpooya
  • 529
  • 1
  • 6
  • 18
  • Doesnt [Windows.Forms.SendKeys]::SendWait('{MButton}') work ? What version of PoSH are you using ? –  Aug 26 '12 at 08:24

2 Answers2

10
function Click-MouseButton
{
param(
[string]$Button, 
[switch]$help)
$HelpInfo = @'

Function : Click-MouseButton
By       : John Bartels
Date     : 12/16/2012 
Purpose  : Clicks the Specified Mouse Button
Usage    : Click-MouseButton [-Help][-Button x]
           where      
                  -Help         displays this help
                  -Button       specify the Button You Wish to Click {left, middle, right}

'@ 

if ($help -or (!$Button))
{
    write-host $HelpInfo
    return
}
else
{
    $signature=@' 
      [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
      public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@ 

    $SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru 
    if($Button -eq "left")
    {
        $SendMouseClick::mouse_event(0x00000002, 0, 0, 0, 0);
        $SendMouseClick::mouse_event(0x00000004, 0, 0, 0, 0);
    }
    if($Button -eq "right")
    {
        $SendMouseClick::mouse_event(0x00000008, 0, 0, 0, 0);
        $SendMouseClick::mouse_event(0x00000010, 0, 0, 0, 0);
    }
    if($Button -eq "middle")
    {
        $SendMouseClick::mouse_event(0x00000020, 0, 0, 0, 0);
        $SendMouseClick::mouse_event(0x00000040, 0, 0, 0, 0);
    }

}


}

You can add this function to your profile, or other script, and then you can call it with:

Click-MouseButton "middle"

John Bartels
  • 2,583
  • 3
  • 19
  • 26
  • this is great except it will only work once - after the type is loaded, `add-type` will throw an exception saying it's already loaded. load the type and then use `[Win32Functions.Win32MouseEventNew]` instead of `$sendmouseclick` – Nacht Jul 14 '14 at 01:11
  • nice answer. [Here](http://www.pinvoke.net/default.aspx/user32/mouse_event.html) one can find more information on the used constants. From it one particularly sees that `0x00000002` corresponds to a left-mouse-down move, whereas `0x00000004` is a left-mouse-up move, and similarly for the other mouse clicks. – davidhigh Nov 01 '16 at 11:34
3

Well, SendKeys is for simulating keyboard input and not mouse input. If there is a keyboard mechanism to invoke the function then you can use SendKeys. For instance, you can send Alt+«char» if there is a keyboard accelerator configured for a control. Of you can send tab keys then a space key to click a button.

As for actually sending keys with PowerShell, first you have to get a handle to the Window that you want to send keystrokes to. How you get that window handle depends on how the window is created. One way is to use the Win32 API FindWindow. Once you have the Window, you need to make sure it is the foreground window (another Win32 API - SetForegroundWindow does that), then you can start sending it keystrokes. PowerShell V2 and higher allow you to access Win32 APIs via the .NET PInvoke mechanism via the Add-Type cmdlet e.g.:

Start-Process calc.exe

$pinvokes = @'
  [DllImport("user32.dll", CharSet=CharSet.Auto)]
  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

  [DllImport("user32.dll")]
  [return: MarshalAs(UnmanagedType.Bool)]
  public static extern bool SetForegroundWindow(IntPtr hWnd);
'@

Add-Type -AssemblyName System.Windows.Forms
Add-Type -MemberDefinition $pinvokes -Name NativeMethods -Namespace MyUtils

$hwnd = [MyUtils.NativeMethods]::FindWindow("CalcFrame", "Calculator")
if ($hwnd)
{
    [MyUtils.NativeMethods]::SetForegroundWindow($hwnd)
    [System.Windows.Forms.SendKeys]::SendWait("6")
    [System.Windows.Forms.SendKeys]::SendWait("*")
    [System.Windows.Forms.SendKeys]::SendWait("7")
    [System.Windows.Forms.SendKeys]::SendWait("=")
}

Another possible way, iff the Window is WinForms (or WPF) based and it is running in your PowerShell process, is to use Reflection to reach into the control you want to send a MButtonClick and invoke OnMouseClick yourself. You need a reference to the control but presumably if it is running in your PowerShell process, you created the control and therefore you have a reference to it.

You might find this MSDN article on UI Automation with Windows PowerShell useful. There is also a MSDN topic on simulating mouse and keyboard input that might be helpful.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369