Closed Timskt closed 1 month ago
Hi! Thanks for posting this issue! This certainly seems weird, but could it be possible that it's an issue with an underlying Windows API, and not with SharpHook?
Could you please try using SendInput
directly to simulate text entry to see whether there is the same problem? If there is, then I don't think I'll be able to do much about it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CRApp {
public static class KeyboardInput {
[DllImport("user32.dll")]
static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
struct INPUT {
public uint type;
public MOUSEKEYBDHARDWAREINPUT mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MOUSEKEYBDHARDWAREINPUT {
[FieldOffset(0)]
public HARDWAREINPUT hi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public MOUSEINPUT mi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT {
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT {
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT {
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
public static int InputText(string text) {
if (string.IsNullOrEmpty(text)) {
return 0;
}
INPUT[] inputs = new INPUT[text.Length * 2];
for (int i = 0, j = 0; i < text.Length; i++, j += 2) {
ushort ch = text[i];
inputs[j] = new INPUT {
type = 1,
mkhi = new MOUSEKEYBDHARDWAREINPUT {
ki = new KEYBDINPUT {
wVk = 0,
wScan = ch,
dwFlags = 0x0004,
time = 0,
dwExtraInfo = IntPtr.Zero
}
}
};
inputs[j + 1] = new INPUT {
type = 1,
mkhi = new MOUSEKEYBDHARDWAREINPUT {
ki = new KEYBDINPUT {
wVk = 0,
wScan = ch,
dwFlags = 0x0004 | 0x0002,
time = 0,
dwExtraInfo = IntPtr.Zero
}
}
};
}
uint result = SendInput((uint) inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
return result > 0 ? text.Length : 0;
}
}
}
I used the above code, but it still doesn't work properly on computer 2. When I tried using Python code, it worked fine on computer 2. Therefore, I envisioned converting strings into hexstrings, and Python code only needed to map hexstrings.
demo
from pynput.keyboard import Key, Controller, KeyCode
import time
import binascii
keyboard = Controller()
time.sleep(1)
kMap = {
'~': '`',
'!': '1',
'@': '2',
'#': '3',
'$': '4',
'%': '5',
'^': '6',
'&': '7',
'*': '8',
'(': '9',
')': '0',
'_': '-',
'+': '=',
'{': '[',
'}': ']',
'|': '\\',
':': ';',
'\"': '\'',
'<': ',',
'>': '.',
'?': '/',
}
def type(s:str):
for c in s:
if ord(c) > 127:
continue
if c == '\n':
c = Key.enter
shift = kMap.get(c) is not None
if shift:
c = kMap.get(c)
if shift:
with keyboard.pressed(Key.shift):
time.sleep(0.01)
keyboard.tap(c)
time.sleep(0.01)
else:
keyboard.tap(c)
# time.sleep(0.01)
s = """你好"""
type(s)
Apparently, SendInput
doesn't send Unicode characters correctly through VDI, at least that's what I think. Your code seems correct - if it doesn't work, then I don't really think I can help here, as I've never worked with VDI and currently don't have time to research it. I think you will have more luck asking around on forums related to VDI, why this happens.
Regarding the Python code - it appears to do something completely different - it just simulates pressing and releasing the specified keys (and you've also added basic Shift handling), but correct me if I'm wrong though. This is not what SharpHook (and SendInput
) does when simulating text entry - it simulates the Unicode characters directly so there is no dependency on whether the Shift key is pressed or not, or a dependency on the current keyboard layout.
I'm going to keep this issue open for some time, but as I've said, I don't think I'll be able to do anything about it, so any help is appreciated.
I'm closing this issue due to inactivity and inability to fix it, but we can continue the discussion, and I will reopen it if anything comes up.
I have two computers. Computer 1 is remotely connected to Computer 2 through VDI. I wrote a WPF program to output the input string to the Notepad of Computer 2 by calling the SimulateTextEntry method. This function works normally on Computer 1 and can output the correct string. However, when I enable the software on Computer 1, call the same method, and move the mouse cursor to Notepad of Computer 2, the output string does not match the input character. In English input method, the input string "11111" becomes "nnnnn=9" on computer 2