打开cmd并读取和写入

时间:2011-12-20 13:14:38

标签: c++ windows cmd dos

我需要启动一个启动命令行的进程(它不应该弹出,所以类似于后台进程)。

然后我需要写东西并定期读取cmd的最后一行。

由于我的C ++技能不是很好,我不知道如何实现这一点。

以伪代码的方式,我想到了这样的事情:

startProcess();
writeToCmd();
readFromCmd() { // Call that every given interval (e.g. 1000 ms)
    if(returnValue >= 100) {
        stopProcess();
    }
}

我很确定它不会那么容易。如果有人可以帮助我,那真的很棒。 该程序适用于Windows。

建议后编辑: 这就是我到目前为止所做的事情(我做的有点不同。)

int errorCode;

// Variables for CreateProcess()
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
PHANDLE hInRead, hInWrite;
LPDWORD bytesWritten, bytesRead;

// The CommandLine input
TCHAR tcsCommandLine[] = _T("cmd /c format H: /fs:FAT32 /V:device");
//TCHAR tcsCommandLine[] = _T("cmd /c start D:\\foo.txt");

sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = true;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW; // SW_HIDE FOR PRODUCTION
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = hInRead;
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);

ZeroMemory(&pi, sizeof(pi));

errorCode = CreatePipe(hInRead, hInWrite, &sa, 0);

info = GetDriveInfo(m_wsNANDMountPoint);

if(info.m_uSizeInMB > 2048) {
    log("Wrong Mounting Point. Device has more than 2GB space.");

    return false;
}
else {
    // Start Formatting
    if(!CreateProcess(NULL, tcsCommandLine,
        NULL, NULL,
        TRUE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, NULL, NULL,
        &si,
        &pi)) {

        log("CreateProcess failed. Could not format Drive");
        return false;
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    WriteFile(hInWrite, "#13#10'J'#13#10", 5, bytesWritten, NULL);
    CloseHandle(hInWrite);

    // Wait until child process exits
    WaitForSingleObject(pi.hProcess, 1100);
}

return true;

经过一些调试后,我发现代码不会在ZeroMemory()处中断,而是在

errorCode = CreatePipe(hInRead, hInWrite, &sa, 0);

出现Access violation writing location错误。我不知道我做错了什么。 如果你们能帮助我,真的很棒。

3 个答案:

答案 0 :(得分:2)

在这个例子中你需要做的是创建一个带有隐藏窗口的控制台。如果您使用CreateProcess启动控制台,则应该能够通过STARTUPINFO结构设置窗口的可见性。

下一步是重定向控制台的输入和输出。您可以通过将3个控制台句柄(输入,输出,错误)附加到管道并从父进程读取它来完成此操作。 This MSDN article描述了如何做到这一点。

答案 1 :(得分:1)

命令行包含两个您感兴趣的部分。

  1. 执行程序的地方
  2. 屏幕上写入内容的缓冲区
  3. 由于您不需要屏幕可见,因此您需要在程序中使用这两项内容。所以从这里开始,忘掉cmd。

    要在程序中执行程序,您有很多方法。如果您希望执行行看起来与您在cmd中编写它的方式完全相同,则可以使用system(尽管Windows版本的fork / exec更有意义)。例如:

    system("my_prog.exe --option file.txt");
    

    my_prog.exe--option作为参数执行file.txt

    现在是第二个,你说你想从cmd读取最后一行。实现这一目标的想法是将所有内容的输出都放在文件中,而不是cmd中。

    如果您只对每个实例的最后一行感兴趣,可以将程序的输出重定向到这样的文件:

    system("my_prog.exe --option file.txt > output.txt");
    

    或者如果你想保留整个历史记录,你可以追加而不是覆盖:

    system("my_prog.exe --option file.txt >> output.txt");
    

    如果您还想重定向stderr,可以写:

    system("my_prog.exe --option file.txt &> output.txt");
    

    符号可能是linuxy,在你的窗口试试它是否有效(手动在正常的cmd)。你也可以搜索谷歌“shell redirect”,你会得到很多结果。

    无论如何,如果你想让cmd的最后一行也包含命令本身,你可以在程序中自己覆盖/附加命令行。

答案 2 :(得分:-1)

让我加上这些优秀的答案:

这个很棒的链接演示了控制台的读写:http://www.adrianxw.dk/SoftwareSite/Consoles/Consoles2.html

要定期处理内容,请使用SetTimer()http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx

SetTimer函数每隔x毫秒执行一次函数。 例: 以下控制台程序的工作方式如下:它使用SetTimer设置计时器 然后在消息循环中循环。消息循环接收并处理WM_TIMER条消息 并且还为每个时间间隔调用计时器回调。 只需将您想要完成的内容放在TimerProc()函数中。

#define STRICT 1 
#include <windows.h>
#include <iostream.h>

VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime) 
{
   //put the stuff you want done in here

  cout << "Doing stuff Time: " << dwTime << '\n';
  cout << "--------------------------------------------------\n" ;
  cout.flush();
}

int main(int argc, char *argv[], char *envp[]) 
{
    int Counter=0;
    int usage_Time_millisec=1000;
    MSG Msg;

    UINT TimerId = SetTimer(NULL, 0, usage_Time_millisec, &TimerProc); //bind TimerProc() to SetTimer() 

    cout << "TimerId: " << TimerId << '\n';

   if (!TimerId) return 16;

   while (GetMessage(&Msg, NULL, 0, 0)) 
   {
        ++Counter;
        if (Msg.message == WM_TIMER)
        cout << "Doing stuff Counter: " << Counter << "; timer message\n";
        else
        cout << "Doing stuff Counter: " << Counter << "; message: " << Msg.message << '\n';
        DispatchMessage(&Msg);
   }

   KillTimer(NULL, TimerId);

return 0;

}