C++没有控制台的 popen 命令

发布于 2024-11-29 11:41:42 字数 131 浏览 1 评论 0原文

当我使用 popen 获取命令的输出(例如 dir)时,它将提示出控制台。

但是,我可以在不出现控制台的情况下获得命令的输出吗?

我正在使用 Visual C++,想要创建一个库来返回某些命令(例如 dir)的输出。

when I use popen to get the output of a command, say dir, it will prompt out a console.

however, can I get the output of a command without the appearance of the console?

I am using Visual C++ and want to make an Library to return the output of some command, say, dir.

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

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

发布评论

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

评论(4

她如夕阳 2024-12-06 11:41:42

假设 Windows(因为这是唯一普遍存在此行为的平台):

CreatePipe() 创建通信所需的管道,并且 CreateProcess 创建子进程。

HANDLE StdInHandles[2]; 
HANDLE StdOutHandles[2]; 
HANDLE StdErrHandles[2]; 

CreatePipe(&StdInHandles[0], &StdInHandles[1], NULL, 4096); 
CreatePipe(&StdOutHandles[0], &StdOutHandles[1], NULL, 4096); 
CreatePipe(&StdErrHandles[0], &StdErrHandles[1], NULL, 4096); 


STARTUPINFO si;   memset(&si, 0, sizeof(si));  /* zero out */ 

si.dwFlags =  STARTF_USESTDHANDLES; 
si.hStdInput = StdInHandles[0];  /* read handle */ 
si.hStdOutput = StdOutHandles[1];  /* write handle */
si.hStdError = StdErrHandles[1];  /* write handle */

/* fix other stuff in si */

PROCESS_INFORMATION pi; 
/* fix stuff in pi */


CreateProcess(AppName, commandline, SECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES, FALSE, CREATE_NO_WINDOW |DETACHED_PROCESS, lpEnvironment, lpCurrentDirectory, &si, &pi); 

这应该不仅仅能让你朝着你想要完成的目标前进。

Assuming Windows (since this is the only platform where this behavior is endemic):

CreatePipe() to create the pipes necessary to communicate, and CreateProcess to create the child process.

HANDLE StdInHandles[2]; 
HANDLE StdOutHandles[2]; 
HANDLE StdErrHandles[2]; 

CreatePipe(&StdInHandles[0], &StdInHandles[1], NULL, 4096); 
CreatePipe(&StdOutHandles[0], &StdOutHandles[1], NULL, 4096); 
CreatePipe(&StdErrHandles[0], &StdErrHandles[1], NULL, 4096); 


STARTUPINFO si;   memset(&si, 0, sizeof(si));  /* zero out */ 

si.dwFlags =  STARTF_USESTDHANDLES; 
si.hStdInput = StdInHandles[0];  /* read handle */ 
si.hStdOutput = StdOutHandles[1];  /* write handle */
si.hStdError = StdErrHandles[1];  /* write handle */

/* fix other stuff in si */

PROCESS_INFORMATION pi; 
/* fix stuff in pi */


CreateProcess(AppName, commandline, SECURITY_ATTRIBUTES, SECURITY_ATTRIBUTES, FALSE, CREATE_NO_WINDOW |DETACHED_PROCESS, lpEnvironment, lpCurrentDirectory, &si, &pi); 

This should more than get you on your way to doing what you wish to accomplish.

落叶缤纷 2024-12-06 11:41:42

也许是这样的?
此代码将返回输出,但必须等待该过程完成。

#include <iostream>
#include <windows.h>

int runCmd(const char* cmd, std::string& outOutput) {

    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;
    HANDLE g_hChildStd_ERR_Rd = NULL;
    HANDLE g_hChildStd_ERR_Wr = NULL;

    SECURITY_ATTRIBUTES sa;
    // Set the bInheritHandle flag so pipe handles are inherited.
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDERR.
    if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDERR is not inherited.
    if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDOUT.
    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDOUT is not inherited

    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    bool bSuccess = FALSE;

    // Set up members of the PROCESS_INFORMATION structure.
    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));

    // Set up members of the STARTUPINFO structure.
    // This structure specifies the STDERR and STDOUT handles for redirection.
    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
    siStartInfo.cb = sizeof(STARTUPINFO);
    siStartInfo.hStdError  = g_hChildStd_ERR_Wr;
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

    // Create the child process.
    bSuccess = CreateProcess(
        NULL,             // program name
        (char*)cmd,       // command line
        NULL,             // process security attributes
        NULL,             // primary thread security attributes
        TRUE,             // handles are inherited
        CREATE_NO_WINDOW, // creation flags (this is what hides the window)
        NULL,             // use parent's environment
        NULL,             // use parent's current directory
        &siStartInfo,     // STARTUPINFO pointer
        &piProcInfo       // receives PROCESS_INFORMATION
    );

    CloseHandle(g_hChildStd_ERR_Wr);
    CloseHandle(g_hChildStd_OUT_Wr);

    // read output
    #define BUFSIZE 4096
    DWORD dwRead;
    CHAR chBuf[BUFSIZE];
    bool bSuccess2 = FALSE;
    for (;;) { // read stdout
        bSuccess2 = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if(!bSuccess2 || dwRead == 0) break;
        std::string s(chBuf, dwRead);
        outOutput += s;
    }
    dwRead = 0;
    for (;;) { // read stderr
        bSuccess2 = ReadFile(g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if(!bSuccess2 || dwRead == 0) break;
        std::string s(chBuf, dwRead);
        outOutput += s;
    }

    // The remaining open handles are cleaned up when this process terminates.
    // To avoid resource leaks in a larger application,
    // close handles explicitly.
    return 0;
}

int main(int argc, char* argv[]) {

    std::string output;
    runCmd("cmd /c dir", output);

    std::cout << output << std::endl;

    return 0;
}

Maybe something like this?
This code will return the output but it has to wait for the process to finish.

#include <iostream>
#include <windows.h>

int runCmd(const char* cmd, std::string& outOutput) {

    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;
    HANDLE g_hChildStd_ERR_Rd = NULL;
    HANDLE g_hChildStd_ERR_Wr = NULL;

    SECURITY_ATTRIBUTES sa;
    // Set the bInheritHandle flag so pipe handles are inherited.
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDERR.
    if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDERR is not inherited.
    if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0))     { return 1; } // Create a pipe for the child process's STDOUT.
    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { return 1; } // Ensure the read handle to the pipe for STDOUT is not inherited

    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    bool bSuccess = FALSE;

    // Set up members of the PROCESS_INFORMATION structure.
    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));

    // Set up members of the STARTUPINFO structure.
    // This structure specifies the STDERR and STDOUT handles for redirection.
    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
    siStartInfo.cb = sizeof(STARTUPINFO);
    siStartInfo.hStdError  = g_hChildStd_ERR_Wr;
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

    // Create the child process.
    bSuccess = CreateProcess(
        NULL,             // program name
        (char*)cmd,       // command line
        NULL,             // process security attributes
        NULL,             // primary thread security attributes
        TRUE,             // handles are inherited
        CREATE_NO_WINDOW, // creation flags (this is what hides the window)
        NULL,             // use parent's environment
        NULL,             // use parent's current directory
        &siStartInfo,     // STARTUPINFO pointer
        &piProcInfo       // receives PROCESS_INFORMATION
    );

    CloseHandle(g_hChildStd_ERR_Wr);
    CloseHandle(g_hChildStd_OUT_Wr);

    // read output
    #define BUFSIZE 4096
    DWORD dwRead;
    CHAR chBuf[BUFSIZE];
    bool bSuccess2 = FALSE;
    for (;;) { // read stdout
        bSuccess2 = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if(!bSuccess2 || dwRead == 0) break;
        std::string s(chBuf, dwRead);
        outOutput += s;
    }
    dwRead = 0;
    for (;;) { // read stderr
        bSuccess2 = ReadFile(g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if(!bSuccess2 || dwRead == 0) break;
        std::string s(chBuf, dwRead);
        outOutput += s;
    }

    // The remaining open handles are cleaned up when this process terminates.
    // To avoid resource leaks in a larger application,
    // close handles explicitly.
    return 0;
}

int main(int argc, char* argv[]) {

    std::string output;
    runCmd("cmd /c dir", output);

    std::cout << output << std::endl;

    return 0;
}
水中月 2024-12-06 11:41:42

对于 POSIX,它应该是这样的:

//Create the pipe.
int lsOutPipe[2];
pipe(lsOutPipe);

//Fork to two processes.
pid_t lsPid=fork();

//Check if I'm the child or parent.
if ( 0 == lsPid )
{//I'm the child.
  //Close the read end of the pipe.
  close(lsOutPipe[0]);

  //Make the pipe be my stdout.
  dup2(lsOutPipe[1],STDOUT_FILENO);

  //Replace my self with ls (using one of the exec() functions):
  exec("ls"....);//This never returns.  
} // if

//I'm the parent.
//Close the read side of the pipe.
close(lsOutPipe[1]);

//Read stuff from ls:
char buffer[1024];
int bytesRead;
do
{
  bytesRead = read(emacsInPipe[0], buffer, 1024);

  // Do something with the read information.
  if (bytesRead > 0) printf(buffer, bytesRead);
} while (bytesRead > 0);

你当然应该检查返回值等......

With POSIX it should be something like this:

//Create the pipe.
int lsOutPipe[2];
pipe(lsOutPipe);

//Fork to two processes.
pid_t lsPid=fork();

//Check if I'm the child or parent.
if ( 0 == lsPid )
{//I'm the child.
  //Close the read end of the pipe.
  close(lsOutPipe[0]);

  //Make the pipe be my stdout.
  dup2(lsOutPipe[1],STDOUT_FILENO);

  //Replace my self with ls (using one of the exec() functions):
  exec("ls"....);//This never returns.  
} // if

//I'm the parent.
//Close the read side of the pipe.
close(lsOutPipe[1]);

//Read stuff from ls:
char buffer[1024];
int bytesRead;
do
{
  bytesRead = read(emacsInPipe[0], buffer, 1024);

  // Do something with the read information.
  if (bytesRead > 0) printf(buffer, bytesRead);
} while (bytesRead > 0);

You should off course check return values etc...

情深如许 2024-12-06 11:41:42

我需要为我的全屏 OpenGL Windows 应用程序解决这个问题,但无法阻止控制台窗口弹出。相反,在短暂的延迟后收回焦点似乎足以避免看到它。

_popen(cmd, "wb");

Sleep(100);

ShowWindow(hWnd, SW_SHOWDEFAULT);
SetForegroundWindow(hWnd);

更新:如果程序是从资源管理器启动的,这显然不起作用。从 Visual Studio 启动时它可以工作。

I needed to solve this for my full screen OpenGL Windows application, but was unable to prevent the console window popping up. Instead, taking back focus after a short delay seems to work well enough to avoid seeing it.

_popen(cmd, "wb");

Sleep(100);

ShowWindow(hWnd, SW_SHOWDEFAULT);
SetForegroundWindow(hWnd);

Update: this apparently doesn't work if the program is launched from Explorer. It is working when launched from Visual Studio.

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