我需要启动一个启动命令行的进程(它不应该弹出,所以类似于后台进程)。
然后我需要写东西并定期读取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
错误。我不知道我做错了什么。
如果你们能帮助我,真的很棒。
答案 0 :(得分:2)
在这个例子中你需要做的是创建一个带有隐藏窗口的控制台。如果您使用CreateProcess启动控制台,则应该能够通过STARTUPINFO结构设置窗口的可见性。
下一步是重定向控制台的输入和输出。您可以通过将3个控制台句柄(输入,输出,错误)附加到管道并从父进程读取它来完成此操作。 This MSDN article描述了如何做到这一点。
答案 1 :(得分:1)
命令行包含两个您感兴趣的部分。
由于您不需要屏幕可见,因此您需要在程序中使用这两项内容。所以从这里开始,忘掉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;
}