4月 04, 2025 C# PowerShell
### 出現問題

最近要為一個沒有 API 的平台制作 Automation,搵過好多唔同既方法,最後發現 stackoverflow 竟然係因最多人推介用 `PowerShell` 來解決,在先前係用過 "按鍵精靈" 同埋 "AutoIT" 的經驗,既然今次又要做 Automation 就不如用啲未用過既方法來開始。

### PowerShell

經過一陣子的研究發現,原來 `PowerShell` 都係需要引入 .dll 程式庫來實現一些原生的 window 功能,而今次我要實行的是模擬 Mouse 及 Keyboard 的動作,對 Web 介面進行 Automation。簡單的追可以通過 WinForms 去實行。

```ps1
// 引入 System.Windows.Forms
Add-Type -AssemblyName System.Windows.Forms
```

然後可以通過直接寫入 C# 代碼到 PowerShell 中即時運行。

以下的代碼是引入了外部的 `user32.dll` 以實行對 Mouse 及 Keyboard 的模擬動作。

```ps1
Add-Type -TypeDefinition @"
using System;
using System.Threading;
using System.Runtime.InteropServices;

/**
 * mouse class
 */
public class Mouse {
    
    // mouse action
    public const uint MOUSEEVENTF_LEFTDOWN = 0x02;
    public const uint MOUSEEVENTF_LEFTUP = 0x04;
    public const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
    public const uint MOUSEEVENTF_RIGHTUP = 0x10;

    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out POINT lpPoint);

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT {
        public int X;
        public int Y;
    }

    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int x, int y);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
}

/**
 * keyboard class
 */
public class Keyboard {

    // keys
    public const byte VK_CONTROL = 0x11;
    public const byte VK_RETURN = 0x0D;
    public const byte VK_A = 0x41;
    public const byte VK_B = 0x42;
    public const byte VK_C = 0x43;
    public const byte VK_D = 0x44;
    public const byte VK_E = 0x45;
    public const byte VK_F = 0x46;
    public const byte VK_G = 0x47;
    public const byte VK_H = 0x48;
    public const byte VK_I = 0x49;
    public const byte VK_J = 0x4A;
    public const byte VK_K = 0x4B;
    public const byte VK_L = 0x4C;
    public const byte VK_M = 0x4D;
    public const byte VK_N = 0x4E;
    public const byte VK_O = 0x4F;
    public const byte VK_P = 0x50;
    public const byte VK_Q = 0x51;
    public const byte VK_R = 0x52;
    public const byte VK_S = 0x53;
    public const byte VK_T = 0x54;
    public const byte VK_U = 0x55;
    public const byte VK_V = 0x56;
    public const byte VK_W = 0x57;
    public const byte VK_X = 0x58;
    public const byte VK_Y = 0x59;
    public const byte VK_Z = 0x5A;
    
    // actions
    public const uint KEYEVENTF_KEYDOWN = 0x0000;
    public const uint KEYEVENTF_KEYUP = 0x0002;

    [DllImport("user32.dll")]
    public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, IntPtr dwExtraInfo);
}
"@
```

當引入完上面的代碼後,可以在下面自己加入你想要運行的代碼去呼叫引入的代碼。

```ps1
// Mouse 左鍵按下
[Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);

// Mouuse 左鍵升起
[Mouse]::mouse_event([Mouse]::MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
```

這樣就可以用 PowerShell 呼叫 C# 來逹成你想要的功能了,正因為呼叫的是 C#,所以是機乎所有的 Window 功能也可以通過 PowerShell 去運行,所以要運行 `.ps1` 的時候可能需要另外的權限。
過去文章
2025 (9)
4 (5)
3 (1)
2 (3)
2024 (25)
11 (3)
10 (3)
9 (1)
3 (18)
2022 (6)
10 (1)
6 (2)
5 (1)
3 (1)
1 (1)
2021 (21)
11 (7)
7 (1)
6 (2)
5 (2)
4 (6)
3 (2)
2 (1)
2020 (92)
12 (1)
11 (2)
10 (4)
9 (10)
8 (5)
7 (1)
6 (3)
5 (1)
4 (4)
3 (25)
2 (7)
1 (29)
2019 (57)
12 (25)
11 (7)
9 (25)