【问题标题】:C Programatically send Enter to cmd.exe by PIDC通过PID以编程方式将Enter发送到cmd.exe
【发布时间】:2021-11-19 18:41:31
【问题描述】:

目标是以编程方式输入某个 cmd.exe(在后台运行,例如由 SYSTEM 用户拥有,从 Windows 服务启动),这将在视觉上产生一个新的空提示行,如“C:\dev\发送者>”。

我在网上找到的所有内容都集中在接收您可以选择检查是否发送了 ascii 代码 10 或 13 的密钥上。但是当将它们发送到正在运行的 cmd.exe 时,所发生的只是你得到一个换行符,但没有新的命令提示符。即使使用 VK_RETURN(应该是回车和换行的别名)也不会出现在新提示中。

我认为问题可能是 WM_KEYUP 之类的必须遵循 ASCII 密钥 10 或 13,但我无法使用下面的最小示例找出如何发送它。

#include <Windows.h>
#include <stdio.h>

//argument: int PID of process
//compile with gcc, no options

//first and only argument: int PID
int main(int argc, char** argv){
    DWORD pid = atoi(argv[1]);
    printf ("Argument PID: %d\n",pid);

    if (!FreeConsole())
    {
        printf("Could not FreeConsole\n");
        exit(1);
    }
    if (!AttachConsole(pid)){
        printf("Error: could not attach console to specified PID\n");
        exit(2);
    }

    char s[] = {VK_RETURN};
    HANDLE stdoutt = GetStdHandle(STD_OUTPUT_HANDLE);
    unsigned long cChars;
    WriteConsole(stdoutt, s, lstrlen(s), &cChars, NULL);

    return 0;
    
}

【问题讨论】:

  • lstrlen() 是否需要以 NUL 结尾的字符串?在这种情况下,您需要char s[] = {VK_RETURN, '\0'};
  • 好点,我不确定在定义 char 数组时是否自动添加空终止符,但我用 char s[] = {VK_RETURN, '\0'};不幸的是,这并没有什么不同。接收命令行只是绘制一个换行符,但不会以新的提示结束
  • 我想你可以试试WriteConsoleInput here 一个样本
  • 我确实阅读了这篇文章但没有尝试,现在我做了但结果对我来说保持不变,不是 100% 确定我是否做了你想到的 @tttony pastebin.com/LCTYGcH1 最后我认为我在连接到另一个控制台后立即写入 stdin 或 stdout 并不重要,至少这是我似乎所经历的

标签: c windows command-line command-line-interface


【解决方案1】:

在 VS 2013 上测试

int main(int argc, char** argv){
    DWORD pid = atoi(argv[1]);

    if (!FreeConsole())
    {
        printf("Could not FreeConsole\n");
        exit(1);
    }
    if (!AttachConsole(pid)){
        printf("Error: could not attach console to specified PID\n");
        exit(2);
    }

    HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
    INPUT_RECORD ir[2];
    DWORD dwTmp = 0;
    
    ir[0].EventType = KEY_EVENT;
    ir[0].Event.KeyEvent.bKeyDown = TRUE;
    ir[0].Event.KeyEvent.dwControlKeyState = 0;
    ir[0].Event.KeyEvent.uChar.UnicodeChar = '\r';
    ir[0].Event.KeyEvent.wRepeatCount = 1;
    ir[0].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
    ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
    
    ir[1].EventType = KEY_EVENT;
    ir[1].Event.KeyEvent.bKeyDown = FALSE;
    ir[1].Event.KeyEvent.dwControlKeyState = 0;
    ir[1].Event.KeyEvent.uChar.UnicodeChar = '\r';
    ir[1].Event.KeyEvent.wRepeatCount = 1;
    ir[1].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
    ir[1].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
    
    WriteConsoleInput(hConsole, ir, 2, &dwTmp); // <-- 2 it's the number of inputs to send

    return 0;
}

我刚刚测试了只打开cmd.exe 并向该进程发送输入,一开始它只在控制台中输入?,那是因为你必须发送两个输入,第一个是bKeyDown 到@ 987654326@ 和更高版本的 FALSEUnicodeChar 设置为 \r 而不是 \n

我还必须将wRepeatCount 设置为1,因为它触发了断言

微软says:

wRepeatCount

重复计数,表示正在按住某个键。为了 例如,当一个键被按住时,你可能会得到五个事件 成员等于 1,此成员等于 5 的一个事件,或多个 此成员大于或等于 1 的事件。

请记住,任何printf 都将被发送到附加的控制台,并且可能会弄乱输入

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    相关资源
    最近更新 更多