micmonay / keybd_event

For simulate key press in Linux, Windows and Mac in golang
MIT License
376 stars 56 forks source link

Send keys to a specific stdin #22

Closed s77rt closed 4 years ago

s77rt commented 4 years ago

Hi, Thank you for your work, this saves time :)

By default the keys seems to be pressed on os.Stdin is it possible to specify another stdin?

Use case: having multiple os/exec programs and need to send specific keys to a specific stdin that's being fed to that specific program

Hope it's clear :)

micmonay commented 4 years ago

The library simulates a keyboard and it has the same output with the hardware keyboard. If you have a solution to set multiple keyboards on various output, it is probably possible. But I don't know if that exists.

(The library does not specify the output)

s77rt commented 4 years ago

I have found a solution for that, but it have nothing to do with the windows api "keybd_event".
So i'm keeping the code here for future ref, hope it helps someone,
also i'm closing this issue for now.

Code: (Windows Only)

func PostKey(pid int, key uint8) (uintptr, error) {
    if runtime.GOOS == "windows" {
        var user32 = syscall.NewLazyDLL("user32.dll")

        EnumWindows := func (enumFunc uintptr, lparam uintptr) {
            user32.NewProc("EnumWindows").Call(uintptr(enumFunc), uintptr(lparam))
        }

        var hwnd uintptr
        cb := syscall.NewCallback(func(h uintptr , prm uintptr) uintptr {
            var itr_pid uint32
            itr_pid = 0x0001
            user32.NewProc("GetWindowThreadProcessId").Call(uintptr(h), uintptr(unsafe.Pointer(&itr_pid)))
            if int(itr_pid) == pid {
                hwnd = h
                user32.NewProc("PostMessageW").Call(h, 0x0100, uintptr(key), 0)
                //return 0 // stop enumeration (commented to make sure all windows created by our process get's the message)
            }
            return 1 // continue enumeration
        })
        EnumWindows(cb, 0)
        if hwnd == 0 {
            return 0, fmt.Errorf("No window with pid %d found", pid)
        }
        return hwnd, nil
    }
    return 0, fmt.Errorf("unsupported os")
}

Example:

PostKey(7777, 0x53) will send the key 'S' to all the windows that are created by the process which it's id is 7777 list of keys

Notes:

If you are using a pid = cmd.Process.Pid (os/exec) your binary should be built passing the "-H=windowsgui" flag