在 PowerShell 中发送鼠标单击事件

Marion Paul Kenneth Mendoza 2022年7月12日
在 PowerShell 中发送鼠标单击事件

在使用 Windows PowerShell 时,我们在为组织或客户开发脚本时可能会或可能不会遇到不寻常的请求,其中一个示例是记录和发送击键。PowerShell 不适合处理击键,因为该函数是脚本库的功能,但尽管有限制,它仍然可以在 PowerShell 中执行。

由于这是一个复杂的主题,在本文中,我们将更多地关注创建和构建发送输入结构以及在我们的脚本中调用发送鼠标单击类。

在 PowerShell 中使用鼠标事件函数

鼠标事件函数 mouse_event() 派生自 Win32 API winuser.h,它从 Microsoft Developer Network (MSDN) 调用 API,特别是从 winuser.h API。开发该 API 是为了调用将处理鼠标事件(包括鼠标单击)的外部 API。

让我们准备我们的 $cSource 变量来建立我们的 INPUT 结构并导入我们需要发送鼠标事件的所有库。

$cSource = @'

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class Clicker{
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
    public int 0;
    public MOUSEINPUT mi;
}

//continued on the following script block

我们已经声明了我们的 INPUT 结构,我们可以使用并调用一个称为 MOUSEINPUT 结构的子结构。请记住,以下代码段仍在 Clicker 类中。

[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
    public int    dx ;
    public int    dy ;
    public int    mouseData ;
    public int    dwFlags;
    public int    time;
    public IntPtr dwExtraInfo;
}

在某些情况下,高级鼠标会有额外的按钮,但现在,由于我们只关注鼠标左键,我们可以在下面声明常用的常量。请注意,我们还为显示器的屏幕长度声明了一个常数。

const int MOUSEEVENTF_MOVED      = 0x0001 ;
const int MOUSEEVENTF_LEFTDOWN   = 0x0002 ;
const int MOUSEEVENTF_LEFTUP     = 0x0004 ;
const int MOUSEEVENTF_RIGHTDOWN  = 0x0008 ;
const int MOUSEEVENTF_RIGHTUP    = 0x0010 ;
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020 ;
const int MOUSEEVENTF_MIDDLEUP   = 0x0040 ;
const int MOUSEEVENTF_WHEEL      = 0x0080 ;
const int MOUSEEVENTF_XDOWN      = 0x0100 ;
const int MOUSEEVENTF_XUP        = 0x0200 ;
const int MOUSEEVENTF_ABSOLUTE   = 0x8000 ;

const int screen_length = 0x10000 ;

现在,我们准备创建一个专门在屏幕上发送左键单击事件的函数。该函数接受两个参数,这些参数将确定在监视器上发生左键单击事件的位置。

[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

public static void LeftClickAtPoint(int x, int y)
{
    //Move the mouse
    INPUT[] input = new INPUT[3];
    input[0].mi.dx = x*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width);
    input[0].mi.dy = y*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
    input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
    //Left mouse button down
    input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    //Left mouse button up
    input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(3, input, Marshal.SizeOf(input[0]));
}
} # Close the Clicker Class
'@ #Close the $cSource variable

要调用我们的左键单击函数,我们必须在 Add-Type cmdlet 下组装库。声明后,我们现在可以调用自定义类 [Clicker]::LeftClickAtPoint(x,y) 在屏幕上发送鼠标左键事件。

Add-Type -TypeDefinition $cSource -ReferencedAssemblies System.Windows.Forms,System.Drawing
[Clicker]::LeftClickAtPoint(300,300)

完整脚本:

$scSource = @'
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class Clicker
{
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
    public int        type; // 0 = INPUT_MOUSE,
                            // 1 = INPUT_KEYBOARD
                            // 2 = INPUT_HARDWARE
    public MOUSEINPUT mi;
}

[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
    public int    dx ;
    public int    dy ;
    public int    mouseData ;
    public int    dwFlags;
    public int    time;
    public IntPtr dwExtraInfo;
}

const int MOUSEEVENTF_MOVED      = 0x0001 ;
const int MOUSEEVENTF_LEFTDOWN   = 0x0002 ;
const int MOUSEEVENTF_LEFTUP     = 0x0004 ;
const int MOUSEEVENTF_RIGHTDOWN  = 0x0008 ;
const int MOUSEEVENTF_RIGHTUP    = 0x0010 ;
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020 ;
const int MOUSEEVENTF_MIDDLEUP   = 0x0040 ;
const int MOUSEEVENTF_WHEEL      = 0x0080 ;
const int MOUSEEVENTF_XDOWN      = 0x0100 ;
const int MOUSEEVENTF_XUP        = 0x0200 ;
const int MOUSEEVENTF_ABSOLUTE   = 0x8000 ;

const int screen_length = 0x10000 ;

[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

public static void LeftClickAtPoint(int x, int y)
{

    INPUT[] input = new INPUT[3];
    input[0].mi.dx = x*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width);
    input[0].mi.dy = y*(65535/System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
    input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
    input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(3, input, Marshal.SizeOf(input[0]));
}
}
'@
Add-Type -TypeDefinition $scSource -ReferencedAssemblies System.Windows.Forms,System.Drawing
[Clicker]::LeftClickAtPoint(300,300)
Marion Paul Kenneth Mendoza avatar Marion Paul Kenneth Mendoza avatar

Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.

LinkedIn