我想使用SendInput()函数登录到我的帐户,就像我亲自做的那样;按回车键,按密码键,再按回车键。
这样做的目的是我写了一个远程连接程序,我可以得到屏幕截图来检查是否一切正常。该程序以任务调度程序开始,所以当我的电脑重启时,我仍然可以发送命令并获得屏幕截图。但是我想添加一个远程登录选项,所以如果我的电脑重启,我可以远程发送信号登录。
它在桌面中工作,但当我用win+L锁定我的用户时,它在锁定屏幕中没有做任何事情,当我登录检查桌面时。
下面是代码
void sendPassword(){
//Map to store keys as char-WORD
QMap<QString, WORD> keyMap;
keyMap["Enter"] = 0x0D;
keyMap["0"] = 0x30; keyMap["1"] = 0x31; keyMap["2"] = 0x32; keyMap["3"] = 0x33;
keyMap["4"] = 0x34; keyMap["5"] = 0x35; keyMap["6"] = 0x36; keyMap["7"] = 0x37;
keyMap["8"] = 0x38; keyMap["9"] = 0x39;
keyMap["A"] = 0x41; keyMap["B"] = 0x42; keyMap["C"] = 0x43; keyMap["D"] = 0x44;
keyMap["E"] = 0x45; keyMap["F"] = 0x46; keyMap["G"] = 0x47; keyMap["H"] = 0x48;
keyMap["I"] = 0x49; keyMap["J"] = 0x4A; keyMap["K"] = 0x4B; keyMap["L"] = 0x4C;
keyMap["M"] = 0x4D; keyMap["N"] = 0x4E; keyMap["O"] = 0x4F; keyMap["P"] = 0x50;
keyMap["Q"] = 0x51; keyMap["R"] = 0x52; keyMap["S"] = 0x53; keyMap["T"] = 0x54;
keyMap["U"] = 0x55; keyMap["V"] = 0x56; keyMap["W"] = 0x57; keyMap["X"] = 0x58;
keyMap["Y"] = 0x59; keyMap["Z"] = 0x5A;
//Get password from file.
QFile passFile("password.txt");
passFile.open(QIODevice::ReadOnly);
QString password = QString::fromUtf8(passFile.readAll()).split("rn")[0].split("n")[0];
passFile.close();
//Initialize inputs array.
INPUT* inputs = new INPUT[password.length()*2+4] {};
//Add enter button to inputs array, key down and up.
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = keyMap["Enter"];
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = keyMap["Enter"];
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
for(int i=0; i<password.length(); i++){
//Add password to inputs array char by char, key down and up.
inputs[i*2+2].type = INPUT_KEYBOARD;
inputs[i*2+2].ki.wVk = keyMap[(QString)password[i]];
inputs[i*2+3].type = INPUT_KEYBOARD;
inputs[i*2+3].ki.wVk = keyMap[(QString)password[i]];
inputs[i*2+3].ki.dwFlags = KEYEVENTF_KEYUP;
}
//Add enter button to inputs array, key down and up.
inputs[password.length()*2+2].type = INPUT_KEYBOARD;
inputs[password.length()*2+2].ki.wVk = keyMap["Enter"];
inputs[password.length()*2+3].type = INPUT_KEYBOARD;
inputs[password.length()*2+3].ki.wVk = keyMap["Enter"];
inputs[password.length()*2+3].ki.dwFlags = KEYEVENTF_KEYUP;
//SendInput, send inputs array.
SendInput(password.length()*2+4, inputs, sizeof(INPUT));
//Delete inputs array.
delete[] inputs;
}
如果这没有办法工作,那么我怎么能达到我的目的?
问题是,当您锁定屏幕时,出于安全原因,Windows会更改显示的会话。用户模式服务和驱动程序在会话0中运行,第一个登录的用户在会话1中运行。本质上,sendInput()
是发送击键到你的桌面,而不是锁屏,锁屏在另一个会话中运行:
https://techcommunity.microsoft.com/t5/ask-the-performance-team/application-compatibility-session-0-isolation/ba-p/372361: ~:文本= % 20第一% 20用户% 20 % 20,使用% 20 % 20目标% 20毫无戒心的% 20用户。amp;文本= % 20 windows vista % 20 200年% % 2 c % 20会议,用户% 20运行% 20 201年% % 20会议。
https://learn.microsoft.com/en-us/previous-versions/bb756986 (v = msdn.10)
您可以创造性地使用CreateProcessAsUserA()
并在lpStartupInfo
参数中指定要使用的桌面来解决这个限制(具体来说,设置STARTUPINFOA
的lpDesktop
)。这将涉及到一个小的子程序,它的唯一目的是解锁屏幕,并让你的父进程运行CreateProcessAsUserA()
的子进程。
https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera
https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
作为一个更简单(也可能更安全)的选择,你试过使用远程桌面吗?