NativeMethods.ps1

if ($IsWindows) {
    Add-Type -TypeDefinition @'
    using System;
    using System.Runtime.InteropServices;
    public static class NativeMethods {
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT { public int X; public int Y; }

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

    [DllImport("user32.dll")]
    public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, UIntPtr dwExtraInfo);

    [DllImport("user32.dll")]
    public static extern short GetAsyncKeyState(int vKey);

    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);
    }
'@
 -PassThru | Out-Null

    function Get-NativeMousePosition {
        $pt = New-Object NativeMethods+POINT
        [NativeMethods]::GetCursorPos([ref]$pt) | Out-Null
        [PSCustomObject]@{ X = $pt.X; Y = $pt.Y }
    }

    function Click-LeftMouse {
        param(
            [int]$X,
            [int]$Y
        )
        # Move cursor first
        [NativeMethods]::SetCursorPos($X, $Y) | Out-Null
        $MOUSEEVENTF_LEFTDOWN = 0x0002
        $MOUSEEVENTF_LEFTUP   = 0x0004
        [NativeMethods]::mouse_event($MOUSEEVENTF_LEFTDOWN, 0, 0, 0, [UIntPtr]::Zero)
        Start-Sleep -Milliseconds 50
        [NativeMethods]::mouse_event($MOUSEEVENTF_LEFTUP, 0, 0, 0, [UIntPtr]::Zero)
    }

    function Any-KeyPressed {
        for ($vk = 1; $vk -lt 256; $vk++) {
            $state = [NativeMethods]::GetAsyncKeyState($vk)
            if (($state -band 0x8000) -ne 0) { return $true }
        }
        return $false
    }

} elseif ($IsMacOS) {
    Add-Type -TypeDefinition @'
    using System;
    using System.Runtime.InteropServices;
    public static class MacNative {
        [StructLayout(LayoutKind.Sequential)]
        public struct CGPoint { public double x; public double y; }

        [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
        public static extern IntPtr CGEventCreate(IntPtr source);

        [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
        public static extern CGPoint CGEventGetLocation(IntPtr evt);

        [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
        public static extern IntPtr CGEventCreateMouseEvent(IntPtr source, int mouseType, CGPoint pos, int mouseButton);

        [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
        public static extern void CGEventPost(int tap, IntPtr evt);

        [DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")]
        public static extern void CFRelease(IntPtr cf);

        [DllImport("/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics")]
        public static extern bool CGWarpMouseCursorPosition(CGPoint newCursorPosition);

        public static CGPoint MakePoint(double x, double y) { CGPoint p; p.x = x; p.y = y; return p; }

        public static void ClickLeft(double x, double y) {
            CGPoint p = MakePoint(x, y);
            // warp the cursor to the position
            CGWarpMouseCursorPosition(p);
            IntPtr down = CGEventCreateMouseEvent(IntPtr.Zero, 1, p, 0);
            CGEventPost(0, down);
            CFRelease(down);
            IntPtr up = CGEventCreateMouseEvent(IntPtr.Zero, 2, p, 0);
            CGEventPost(0, up);
            CFRelease(up);
        }
    }
'@
 -PassThru | Out-Null

    function Get-NativeMousePosition {
        $evt = [MacNative]::CGEventCreate([IntPtr]::Zero)
        $pt = [MacNative]::CGEventGetLocation($evt)
        [MacNative]::CFRelease($evt)
        [PSCustomObject]@{ X = [int][math]::Round($pt.x); Y = [int][math]::Round($pt.y) }
    }

    function Click-LeftMouse {
        param(
            [int]$X,
            [int]$Y
        )
        [MacNative]::ClickLeft([double]$X, [double]$Y)
    }

    function Any-KeyPressed {
        if ($Host -and $Host.UI -and $Host.UI.RawUI -and $Host.UI.RawUI.KeyAvailable) {
            # consume the key so it's not left in the buffer
            $null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
            return $true
        }
        return $false
    }

} else {
    throw "Unsupported platform for NativeMethods: $PSVersionTable.Platform"
}