windows 打开cmd并对其进行读写
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8576035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
open cmd and read and write into it
提问by Johannes Klau?
I need to start a process that starts the commandline (it should not pop up, so something like a background process).
我需要启动一个启动命令行的进程(它不应该弹出,所以类似于后台进程)。
Then I need to write stuff to it and periodically read the last line of the cmd.
然后我需要向它写入内容并定期读取 cmd 的最后一行。
Since my C++ skills aren't that great I don't know how to achieve this.
由于我的 C++ 技能不是很好,我不知道如何实现这一点。
In a pseudocode way I thought about something like this:
以伪代码的方式,我想到了这样的事情:
startProcess();
writeToCmd();
readFromCmd() { // Call that every given interval (e.g. 1000 ms)
if(returnValue >= 100) {
stopProcess();
}
}
I'm pretty sure it'll not be that easy. It would be really great if someone can help me out here. The programm is for windows.
我很确定这不会那么容易。如果有人能在这里帮助我,那就太好了。该程序适用于Windows。
Edit after the suggestions: This is what I've done so far (I did it a little bit different.)
在建议之后编辑:这是我到目前为止所做的(我做的有点不同。)
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;
After a little bit of debugging, I recognized that the code doesn't break at ZeroMemory()
, but on
经过一些调试后,我认识到代码不会在 处中断ZeroMemory()
,而是在
errorCode = CreatePipe(hInRead, hInWrite, &sa, 0);
with an Access violation writing location
error. I have no idea what I'm doing wrong.
It would be really great if you guys could help me out.
有Access violation writing location
错误。我不知道我做错了什么。如果你们能帮我一下,那真是太好了。
回答by Mike Kwan
What you need to do in this instance is to create a console with a hidden window. If you use CreateProcessto launch the console, you should be able to set the visibility of the window through the STARTUPINFOstructure.
在这种情况下,您需要做的是创建一个带有隐藏窗口的控制台。如果您使用CreateProcess来启动控制台,您应该能够通过STARTUPINFO结构设置窗口的可见性。
The next step is to redirect the input and output of your console. You can do this by attaching the 3 console handles (input, output, error) to pipes and reading that from your parent process. This MSDN articledescribes how to do exactly this.
下一步是重定向控制台的输入和输出。您可以通过将 3 个控制台句柄(输入、输出、错误)附加到管道并从您的父进程中读取来做到这一点。这篇 MSDN 文章描述了如何做到这一点。
回答by Shahbaz
The command line consists of two parts you would be interested in.
命令行由您感兴趣的两部分组成。
- A place to execute programs
- A buffer for whatever is written on the screen
- 执行程序的地方
- 任何写在屏幕上的缓冲区
Since you don't need the screen to be visible, then you need these two things in your program. So from here on, forget about cmd.
既然您不需要屏幕可见,那么您的程序中就需要这两件事。所以从这里开始,忘记 cmd。
To execute programs in your program, you have many ways. If you want the execution lines to look exactly the way you write it in cmd, you can use system
(although Windows versions of fork/exec make more sense). For example:
要在您的程序中执行程序,您有多种方法。如果您希望执行行看起来与您在 cmd 中编写的方式完全相同,则可以使用system
(尽管 Windows 版本的 fork/exec 更有意义)。例如:
system("my_prog.exe --option file.txt");
Which executes my_prog.exe
with --option
and file.txt
as arguments.
它my_prog.exe
以--option
和file.txt
作为参数执行。
Now the second one, you said you wanted to read the last line from cmd. The idea to realize this is to have the output of everything in a file, instead of in cmd.
现在是第二个,你说你想从 cmd 读取最后一行。实现这一点的想法是将所有内容的输出都放在一个文件中,而不是在 cmd 中。
If you are only interested in the last line at every instance, you can redirect the output of your programs to a file like this:
如果您只对每个实例的最后一行感兴趣,您可以将程序的输出重定向到这样的文件:
system("my_prog.exe --option file.txt > output.txt");
or if you want to keep the whole history, you can append instead of overwrite:
或者如果你想保留整个历史,你可以追加而不是覆盖:
system("my_prog.exe --option file.txt >> output.txt");
If you also want to redirect stderr
, you can write:
如果你还想重定向stderr
,你可以写:
system("my_prog.exe --option file.txt &> output.txt");
The notation may be linuxy, try it in your windows see if it works (manually in a normal cmd). You could also search google for "shell redirect" and you get a lot of results.
符号可能是 linuxy,在您的 Windows 中尝试一下,看看它是否有效(在普通的 cmd 中手动)。你也可以在谷歌上搜索“shell redirect”,你会得到很多结果。
Anyway, if you want the last line of cmd to also include the command itself, you can overwrite/append the command line to that particular yourself in the program.
无论如何,如果您希望 cmd 的最后一行也包含命令本身,您可以在程序中将命令行覆盖/附加到特定的自己。
回答by Software_Designer
Let me add this to these excellent answers:
让我将其添加到这些出色的答案中:
This great link demonstrates console read and write : http://www.adrianxw.dk/SoftwareSite/Consoles/Consoles2.html
这个很棒的链接演示了控制台读写:http: //www.adrianxw.dk/SoftwareSite/Consoles/Consoles2.html
To do stuff periodically, use SetTimer()
.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx
要定期执行操作,请使用SetTimer()
.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx
The SetTimer
function executes a function every x milliseconds.
Example:
The following console program works like this: It sets a timer using SetTimer
then loops in a message loop. The message loop receives and processes WM_TIMER
messages
and the timer callback also is called for each time interval.
Simply put the stuff you want done in the TimerProc()
function.
该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;
}