### 出現問題
最近要為一個沒有 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` 的時候可能需要另外的權限。