C # / Powershell отправить комбинацию клавиш - PullRequest
0 голосов
/ 21 мая 2019

Я обнаружил, что эта функция использует код C # для имитации нажатия клавиш через PowerShell.

Я могу имитировать клавиши WINDOWS следующим образом:

[KBEmulator]::SendScanCode(0x5B)

Однако я хочу отправитькомбинация WINDOWS + CTRL + SHIFT + B

Который с точки зрения ScanCode:

0x5B + 0x11 + 0x10 + 0x42 

К сожалению, я свободно владею PowerShell и не знаю, когда речь заходит о C #.

Есть ли способ, которым я мог бы адаптировать этот код, чтобы брать комбинацию клавиш вместо одной клавиши за раз?

Функция Нажатие клавиши:

Function KeyPress {

Param (
    [Parameter(position=0, mandatory=$true, parametersetname='key')]
    [char]$Key,
    [Parameter(position=0, mandatory=$true, parametersetname='scancode')]
    [int]$ScanCode
)

$code = @"
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public static class KBEmulator {    
    public enum InputType : uint {
        INPUT_MOUSE = 0,
        INPUT_KEYBOARD = 1,
        INPUT_HARDWARE = 3
    }

    [Flags]
    internal enum KEYEVENTF : uint
    {
        KEYDOWN = 0x0,
        EXTENDEDKEY = 0x0001,
        KEYUP = 0x0002,
        SCANCODE = 0x0008,
        UNICODE = 0x0004
    }

    [Flags]
    internal enum MOUSEEVENTF : uint
    {
        ABSOLUTE = 0x8000,
        HWHEEL = 0x01000,
        MOVE = 0x0001,
        MOVE_NOCOALESCE = 0x2000,
        LEFTDOWN = 0x0002,
        LEFTUP = 0x0004,
        RIGHTDOWN = 0x0008,
        RIGHTUP = 0x0010,
        MIDDLEDOWN = 0x0020,
        MIDDLEUP = 0x0040,
        VIRTUALDESK = 0x4000,
        WHEEL = 0x0800,
        XDOWN = 0x0080,
        XUP = 0x0100
    }

    // Master Input structure
    [StructLayout(LayoutKind.Sequential)]
    public struct lpInput {
        internal InputType type;
        internal InputUnion Data;
        internal static int Size { get { return Marshal.SizeOf(typeof(lpInput)); } }            
    }

    // Union structure
    [StructLayout(LayoutKind.Explicit)]
    internal struct InputUnion {
        [FieldOffset(0)]
        internal MOUSEINPUT mi;
        [FieldOffset(0)]
        internal KEYBDINPUT ki;
        [FieldOffset(0)]
        internal HARDWAREINPUT hi;
    }

    // Input Types
    [StructLayout(LayoutKind.Sequential)]
    internal struct MOUSEINPUT
    {
        internal int dx;
        internal int dy;
        internal int mouseData;
        internal MOUSEEVENTF dwFlags;
        internal uint time;
        internal UIntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct KEYBDINPUT
    {
        internal short wVk;
        internal short wScan;
        internal KEYEVENTF dwFlags;
        internal int time;
        internal UIntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct HARDWAREINPUT
    {
        internal int uMsg;
        internal short wParamL;
        internal short wParamH;
    }

    private class unmanaged {
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern uint SendInput (
            uint cInputs, 
            [MarshalAs(UnmanagedType.LPArray)]
            lpInput[] inputs,
            int cbSize
        );

        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern short VkKeyScan(char ch);
    }

    internal static short VkKeyScan(char ch) {
        return unmanaged.VkKeyScan(ch);
    }

    internal static uint SendInput(uint cInputs, lpInput[] inputs, int cbSize) {
        return unmanaged.SendInput(cInputs, inputs, cbSize);
    }

    public static void SendScanCode(short scanCode) {
        lpInput[] KeyInputs = new lpInput[1];
        lpInput KeyInput = new lpInput();
        // Generic Keyboard Event
        KeyInput.type = InputType.INPUT_KEYBOARD;
        KeyInput.Data.ki.wScan = 0;
        KeyInput.Data.ki.time = 0;
        KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;


        // Push the correct key
        KeyInput.Data.ki.wVk = scanCode;
        KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
        KeyInputs[0] = KeyInput;
        SendInput(1, KeyInputs, lpInput.Size);

        // Release the key
        KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
        KeyInputs[0] = KeyInput;
        SendInput(1, KeyInputs, lpInput.Size);

        return;
    }

    public static void SendKeyboard(char ch) {
        lpInput[] KeyInputs = new lpInput[1];
        lpInput KeyInput = new lpInput();
        // Generic Keyboard Event
        KeyInput.type = InputType.INPUT_KEYBOARD;
        KeyInput.Data.ki.wScan = 0;
        KeyInput.Data.ki.time = 0;
        KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;


        // Push the correct key
        KeyInput.Data.ki.wVk = VkKeyScan(ch);
        KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
        KeyInputs[0] = KeyInput;
        SendInput(1, KeyInputs, lpInput.Size);

        // Release the key
        KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
        KeyInputs[0] = KeyInput;
        SendInput(1, KeyInputs, lpInput.Size);

        return;
    }
}
"@

if(([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{$_ -match "KBEmulator"}) -eq $null) {
    Add-Type -TypeDefinition $code
}

switch($PSCmdlet.ParameterSetName){
    'key' { [KBEmulator]::SendKeyboard($Key) }
    'scancode' { [KBEmulator]::SendScanCode($ScanCode) }
}

}

[KBEmulator]::SendScanCode(0x5B)

1 Ответ

1 голос
/ 21 мая 2019

Вот моя попытка, должно быть с чего начать.Некоторое время назад я не делал никакого кода на C #, поэтому не уверен, как именно в нем программировать, но, надеюсь, он должен принимать массив символов, нажимать клавиши в массиве и отправлять как структуру массива.Цикл for может быть индексом выключен, хотя и не уверен, и может быть случайная ошибка, которую я не осознавал в коде, и я даже не уверен, будет ли она выполнять все нажатия клавиш одновременно или по одному,но, надеюсь, это поможет вам с чего начать.

public static void SendKeyboard(char ch) {
    lpInput[] KeyInputs = new lpInput[1];
    lpInput KeyInput = new lpInput();
    // Generic Keyboard Event
    KeyInput.type = InputType.INPUT_KEYBOARD;
    KeyInput.Data.ki.wScan = 0;
    KeyInput.Data.ki.time = 0;
    KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;


    // Push the correct key
    KeyInput.Data.ki.wVk = VkKeyScan(ch);
    KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
    KeyInputs[0] = KeyInput;
    SendInput(1, KeyInputs, lpInput.Size);

    // Release the key
    KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
    KeyInputs[0] = KeyInput;
    SendInput(1, KeyInputs, lpInput.Size);

    return;  
    }

 // Attempt at overloading for multiple key presses
 public static void SendKeyboard(char[] ch) {
    lpInput[] KeyInputs = new lpInput[ch.length];

    // Push the correct key
    for (int i = 0; i < ch.length; i++) {
    // Generate new memory address for KeyInput each time
    lpInput KeyInput = new lpInput();
    // Generic Keyboard Event
    KeyInput.type = InputType.INPUT_KEYBOARD;
    KeyInput.Data.ki.wScan = 0;
    KeyInput.Data.ki.time = 0;
    KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
    KeyInput.Data.ki.wVk = VkKeyScan(ch[i]);
    KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYDOWN;
    KeyInputs[i] = KeyInput;
    }
    SendInput( ch.length, KeyInputs, ( lpInput.Size * ch.length ) );

    // Release the key
    for (int i = 0; i < ch.length; i++) {
    // Generate new memory address for KeyInput each time
    lpInput KeyInput = new lpInput();
    // Generic Keyboard Event
    KeyInput.type = InputType.INPUT_KEYBOARD;
    KeyInput.Data.ki.wScan = 0;
    KeyInput.Data.ki.time = 0;
    KeyInput.Data.ki.dwExtraInfo = UIntPtr.Zero;
    KeyInput.Data.ki.wVk = VkKeyScan(ch[i]);
    KeyInput.Data.ki.dwFlags = KEYEVENTF.KEYUP;
    KeyInputs[i] = KeyInput;
    }
    SendInput(ch.length, KeyInputs, ( lpInput.Size * ch.length ) );

    return;  
    }
...