【问题标题】:How to execute commands in the same process如何在同一进程中执行命令
【发布时间】:2020-04-05 17:53:09
【问题描述】:

我创建了自己的函数来执行命令并保存结果。问题是命令执行一次,我无法执行具有相同“上下文”的多个命令。例如。如果我执行cd ..,我的cd .. 的下一个命令将被忽略。这是我的代码:

std::string executeCommand(const std::string& cmd)
{
    system((cmd + " > temp.txt").c_str());
    std::ifstream ifs("temp.txt");
    std::string ret{ std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>() };
    ifs.close(); // must close the inout stream so the file can be cleaned up
    return ret;
}

我可以有这个功能的样品吗?

【问题讨论】:

  • system() 生成一个单独的进程来运行指定的命令行。当该过程结束时,它对其环境所做的任何事情都会丢失。因此,要么将多个命令放在一个命令行中,要么根本不使用system() 来执行命令。

标签: c++ cmd process pipe


【解决方案1】:

你用的是Windows系统吗? 在 Windows 中,您可以通过 Pipe 与 cmd 进行交互。

像这样:

#define BUFFER_SIZE 131072 //128*1024‬
void work() {
    HANDLE hinRead, hinWrite, houtRead, houtWrite;

    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = 0;
    sa.bInheritHandle = true;

    if (!CreatePipe(&hinRead, &hinWrite, &sa, 0)) {
        MessageBoxA(NULL, "Error CreatePipe", "Error", MB_ICONERROR);
    }
    if (!CreatePipe(&houtRead, &houtWrite, &sa, 0)) {
        MessageBoxA(NULL, "Error CreatePipe", "Error", MB_ICONERROR);
    }

    STARTUPINFOA si;
    ZeroMemory(&si, sizeof(si));
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;
    si.hStdInput = hinRead;//redirect Input
    si.hStdOutput = si.hStdError = houtWrite;//redirect Output

    PROCESS_INFORMATION ProcessInformation;
    char cmdLine[256] = { 0 };
    GetSystemDirectoryA(cmdLine, sizeof(cmdLine));
    strcat(cmdLine, ("\\cmd.exe"));
    if (CreateProcessA(cmdLine, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &ProcessInformation) == 0) {
        MessageBoxA(NULL, "Error CreateProcessA", "Error", MB_ICONERROR);
    }

    char* pbuff = new char[BUFFER_SIZE];
    DWORD dw;
    Sleep(100);//wait cmd start
    ReadFile(houtRead, pbuff, BUFFER_SIZE-1, &dw, NULL);
    pbuff[dw] = 0;
    printf(pbuff);//version info

    while (1) {
        char* p = pbuff;
        while ((*p = getchar()) != '\n') {
            ++p;
        }
        WriteFile(hinWrite, pbuff, p - pbuff + 1, &dw, 0);
        while (1) {
            ReadFile(houtRead, pbuff, BUFFER_SIZE - 1, &dw, NULL);
            pbuff[dw] = 0;
            printf("%s", pbuff);
            if (pbuff[dw - 1] == '>')break;
        }
    }
}

管道可以像文件一样读/写。

在其他系统中,也有类似管道的东西,但我不熟悉。

编辑:另一个更清晰的例子

int main() {

    HANDLE hinRead, hinWrite, houtRead, houtWrite;

    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = 0;
    sa.bInheritHandle = true;

    if (!CreatePipe(&hinRead, &hinWrite, &sa, 0)) {
        MessageBoxA(NULL, "Error CreatePipe", "Error", MB_ICONERROR);
    }
    if (!CreatePipe(&houtRead, &houtWrite, &sa, 0)) {
        MessageBoxA(NULL, "Error CreatePipe", "Error", MB_ICONERROR);
    }

    STARTUPINFOA si;
    ZeroMemory(&si, sizeof(si));
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = SW_HIDE;//no window
    si.hStdInput = hinRead;//redirect Input
    si.hStdOutput = si.hStdError = houtWrite;//redirect Output

    PROCESS_INFORMATION pi;
    char cmdLine[256] = { 0 };
    GetSystemDirectoryA(cmdLine, sizeof(cmdLine));
    strcat(cmdLine, ("\\cmd.exe"));
    if (CreateProcessA(cmdLine, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0) {
        MessageBoxA(NULL, "Error CreateProcessA", "Error", MB_ICONERROR);
    }

    Sleep(100);//wait cmd start

    char* pbuff = new char[1024 * 128];
    DWORD dw;

    ReadFile(houtRead, pbuff, 1024 * 128, &dw, NULL), pbuff[dw] = 0, printf("%s", pbuff);//cmd version info


    WriteFile(hinWrite, "cd ..\n", 6, &dw, NULL);//send command to cmd.exe

    Sleep(100);//wait command execute and cmd outputs
    ReadFile(houtRead, pbuff, 1024 * 128, &dw, NULL), pbuff[dw] = 0, printf("%s", pbuff);


    WriteFile(hinWrite, "dir\n", 4, &dw, NULL);//another command
    Sleep(100);
    ReadFile(houtRead, pbuff, 1024 * 128, &dw, NULL), pbuff[dw] = 0, printf("%s", pbuff);

    delete[] pbuff;
    TerminateProcess(pi.hProcess, 0);//Terminate cmd.exe
    return 0;
}

【讨论】:

  • 非常感谢您的回答。您的代码编译完美(只需在项目预处理器设置中添加 _CRT_SECURE_NO_WARNINGS)。但是,我怎样才能一个接一个地执行命令?感谢您的帮助!
  • 当你想执行一个命令时。用WriteFile将它写入管道。 (hinWrite ----- 表示 cmd.exe 输入的编写器句柄) 命令将在相同的“上下文”中执行
  • 记得最后使用TerminateProcess(ProcessInformation.hProcess, 0)来终止cmd.exe。
  • 嘿!您能否编辑您的答案以创建一个 main() 函数并执行两个命令以使您的示例更加清晰?谢谢。
  • 已编辑.__@TomS.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
相关资源
最近更新 更多