在 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