2011-12-20 86 views
0

我需要启动一个启动命令行的进程(它不应该弹出,所以像后台进程)。打开cmd并读取和写入它

然后我需要写东西给它并定期读取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错误。我不知道我在做什么错。 如果你们能够帮助我,这将会非常棒。

+2

这并没有多大意义。你能否提供一些有关实际问题的更多细节,而不是你如何设想解决方案的外观。无论问题出在哪,每秒轮询肯定不是解决方案。 – 2011-12-20 13:16:55

回答

1

命令行由两个部分组成,你会感兴趣的

  1. 执行程序
  2. 一种无论是在屏幕

既然你不上写缓冲的地方t需要屏幕可见,那么你的程序需要这两样东西。所以从这里开始,忘了cmd。

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

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

其执行my_prog.exe--optionfile.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,请在您的Windows中尝试它,看看它是否工作(手动在一个普通的cmd中)。你也可以搜索谷歌的“外壳重定向”,你会得到很多结果。

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

+0

好主意。在Windows 7上,命令语法也适用于我,关于'>'和'>>'。 – 2017-01-04 16:38:08

2

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

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

+0

我试过了。但是我总是在这一行上遇到'访问冲突写入位置...'错误:'ZeroMemory(&si,sizeof(STARTUPINFO));' – 2011-12-20 14:24:53

+0

除非'si'被写保护(读-只要)。在原始问题中发布您当前的努力,我们可以为您提供更多帮助。 – 2011-12-20 15:23:50

-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; 

} 
+0

用计时器轮询不是答案。 – 2011-12-21 07:54:10