打开cmd并对其进行读写

发布于 2024-12-22 03:17:42 字数 2142 浏览 2 评论 0原文

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

然后我需要向其中写入内容并定期读取 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);

写入位置访问冲突错误。我不知道我做错了什么。 如果你们能帮助我,那就太好了。

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.

Since my C++ skills aren't that great I don't know how to achieve this.

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.

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

看轻我的陪伴 2024-12-29 03:17:42

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

下一步是重定向控制台的输入和输出。您可以通过将 3 个控制台句柄(输入、输出、错误)附加到管道并从父进程中读取它来完成此操作。 这篇 MSDN 文章 详细介绍了如何执行此操作。

What you need to do in this instance is to create a console with a hidden window. If you use CreateProcess to launch the console, you should be able to set the visibility of the window through the STARTUPINFO structure.

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 article describes how to do exactly this.

趁年轻赶紧闹 2024-12-29 03:17:42

命令行由您感兴趣的两部分组成。

  1. 执行程序的地方
  2. 屏幕上写入的内容的缓冲区

由于您不需要屏幕可见,因此您的程序中需要这两部分。所以从现在开始,忘掉cmd吧。

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

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

--optionfile.txt 作为参数执行 my_prog.exe

现在是第二个,你说你想从 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中手动)。您还可以在谷歌上搜索“shell重定向”,您会得到很多结果。

无论如何,如果您希望 cmd 的最后一行也包含命令本身,您可以在程序中自己将命令行覆盖/附加到该特定行。

The command line consists of two parts you would be interested in.

  1. A place to execute programs
  2. 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.

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:

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

Which executes my_prog.exe with --option and file.txt as arguments.

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.

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:

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.

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.

苍景流年 2024-12-29 03:17:42

让我将其添加到这些出色的答案中:

这个很棒的链接演示了控制台读写: 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;

}

Let me add this to these excellent answers:

This great link demonstrates console read and write : 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

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.

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文