イネマルのプログラミング備忘録

だいたい付箋。一口サイズのメモ帳

C++ で、コマンドの標準出力を取得する方法(CreateProcessなし)

はじめに

Windows でコマンドを実行する際、標準出力を取得する方法です。
コンソール画面が表示されても問題ない場合、
もしくは、CUIプログラムで使用できる方法です。

前提

system 関数だけでは、標準出力が簡単に取得できません。
Windows 環境では、APIの CreateProcess を使用する方法が良く使用されますが、popen を使用した方がシンプルに実装できます。

標準エラーの対応は、行っていませんが、
表示したくない場合は、実行コマンド末尾に「 2>&1」を付けて標準出力にリダイレクトする等
適宜対応しましょう。

実装

#include <array>  // array
#include <cstdio>    // _popen
#include <iostream>  // cout
#include <memory>    // shared_ptr
#include <string>    // string

bool ExecCmd(const char* cmd, std::string& stdOut, int& exitCode) {
    std::shared_ptr<FILE> pipe(_popen(cmd, "r"), [&](FILE* p) {exitCode = _pclose(p); });
    if (!pipe) {
        return false;
    }
    std::array<char, 256> buf;
    while (!feof(pipe.get())) {
        if (fgets(buf.data(), buf.size(), pipe.get()) != nullptr) {
            stdOut += buf.data();
        }
    }
    return true;
}

int main(int argc, char** argv)
{
    // 適当なコマンドを用意する
    const char* cmd = "dir";
    std::string stdOut;
    int exitCode;
    if (ExecCmd(cmd, stdOut, exitCode)) {
        std::cout << stdOut << std::endl;
    }
    else {
        std::cout << "標準出力の取得に失敗しました。" << std::endl;
    }

    system("pause");
    return 0;
}

あとがき

Windows では、popen が使用できないと思い込んでいましたが、
_popen の名前で、使用できるので、実装して備忘録行き。