• ベストアンサー
  • 困ってます

標準出力をDOS窓を開かずにファイルに書き込む方法

  • 質問No.2286377
  • 閲覧数743
  • ありがとう数2
  • 回答数5

お礼率 78% (97/123)

VC++(Console Appli)です。

あるコマンドの標準出力結果をファイルに吐き出す方法として、
単純には、
system("cmnd > C:\\temp.txt");
とやれば実現できますが、このとき、一瞬ですが、DOS窓の黒枠が表示されます。
このDOS窓を出さないで済む方法があれば教えてください。

標準出力を何らかの方法で受け取って、
-------------------------------------------------
CString str;
CStdioFile file;
  :
 cmndの標準出力結果をstrへ内部的に受け取らせる。
  :
file.Open(_T("c:\\temp.txt"), CFile::modeWrite);
file.WriteString(str);
file.Close();
-------------------------------------------------

などで簡単に出来れば良いのですが・・よろしくお願いします。

質問者が選んだベストアンサー

  • 回答No.5
  • ベストアンサー

ベストアンサー率 62% (800/1280)

#include <windows.h>
#include <stdio.h>

int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
SECURITY_ATTRIBUTES pa, ta;
BOOL bInheritHandles = TRUE;
DWORD dwCreationFlags;
LPVOID lpEnv = NULL;
LPCSTR lpCurDir = NULL;
STARTUPINFO info;
PROCESS_INFORMATION pi;
HANDLE hStdIn, hStdOut;
char buff[1024];
DWORD readsize;
FILE *fp;

dwCreationFlags = CREATE_NEW_CONSOLE;

ZeroMemory(&pi, sizeof pi);

ZeroMemory(&pa, sizeof pa);
pa.nLength = sizeof pa;
pa.lpSecurityDescriptor = NULL;
pa.bInheritHandle = TRUE;

ZeroMemory(&ta, sizeof ta);
ta.nLength = sizeof ta;
ta.lpSecurityDescriptor = NULL;
ta.bInheritHandle = TRUE;

if (!CreatePipe(&hStdIn, &hStdOut, &pa, 0))
return 2;

ZeroMemory(&info, sizeof info);
info.cb = sizeof info;
info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ;
info.hStdOutput = hStdOut;
info.hStdError = hStdOut;
info.hStdInput = INVALID_HANDLE_VALUE;
info.wShowWindow = SW_HIDE;

if(!CreateProcess(NULL, "ls -l", &pa, &ta,
TRUE, CREATE_DEFAULT_ERROR_MODE,
NULL, NULL, &info, &pi))
return 3;

WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(hStdOut);

fp = fopen("o.txt", "w");
if (!fp)
return 4;

while (ReadFile(hStdIn, buff, sizeof buff, &readsize, NULL))
fwrite(buff, readsize, 1, fp);

return 0;
}
補足コメント
goku3

お礼率 78% (97/123)

お礼が遅くなりすみませんでした。
結局、まだ検証が中途半端なままなのですが、
一応DOS窓が消して実行できる状態にはなっています。
また何かあれば具体的症状を沿えて別upするようにします。
投稿日時:2006/09/13 14:36
お礼コメント
goku3

お礼率 78% (97/123)

長い間が開いてしまい、すみませんでした。
ご丁寧なご回答ありがとうございました。
投稿日時:2006/09/13 14:36

その他の回答 (全4件)

  • 回答No.4

ベストアンサー率 62% (800/1280)

乗りかかった船、ということでやってみました。
短くするためところとことん切り詰めましたが、それでも
1600バイトをようやく切るぐらいになったしまったので次の発言に
プログラムを貼り付けます。
一応、Windows 2000上で正常動作することは確認しています。

使うときにはエラーチェックをしっかりやってください。
お礼コメント
goku3

お礼率 78% (97/123)

えっ!、と思わず驚いています。
わざわざ、ありがとうございました。

今日は半日、これで潰れてしまい、諦めかけていました。
動作確認してみます。
本当にありがとうございました。
投稿日時:2006/07/20 18:38
  • 回答No.3

ベストアンサー率 62% (800/1280)

連続して発言してすみません。
よく読み返したら、コンソールアプリから呼び出しって書いてありますね。
であれば、

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
int
main()
{
  const char* cmd = "ls";
  FILE *fp;
  char buf[1024];

  fp = _popen(cmd, "r");
  if (!fp) {
    fprintf(stderr, "can't execute %s\n", cmd);
    exit(1);
  }

  while (fgets(buf, sizeof buf, fp))
    printf("get: %s\n", buf);

  close(fp);

  return 0;
}

で、新しいコンソールは出てきませんでしたけど?
補足コメント
goku3

お礼率 78% (97/123)

すみませんでした。
コンソールアプリというのが嘘で、実際は、
cmdDlg.cppファイルで
//cmdDlg ダイアログ
//cmdDlg メッセージ ハンドラ
などの処理も入っています。

CreateProcessを駆使して・・・、かなり以前にもこちらで教えて頂きながらチャレンジしたのですが、どうにも自分の理解能力を超えていて、いま、少しあきらめかけています。

一縷の望みは、
CreateProcess() の引数 STARTUPINFO 構造体にある
hStdOutput に何か出力されるように思っています。

これをファイルに受けられればと思っています。
投稿日時:2006/07/20 14:56
  • 回答No.2

ベストアンサー率 62% (800/1280)

↓こんなので試してみましたが、コマンドの出力は受け取れたものの
コンソールが表示されてしまいました。
どうも WindowsAPI の CreateProcessを駆使して処理する必要があるようです。

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>

//#define CMD "cmd.exe /c dir /od"
#define CMD "ls.exe -l"

int WINAPI WinMain(
  HINSTANCE hInstance,
  HINSTANCE hPrevInstance,
  LPSTR lpCmdLine,
  int nCmdShow
)
{
  const char* cmd = CMD;
  FILE *ifp;
  FILE *ofp;
  char buf[1024];

  ifp = _popen(cmd, "r");
  if (!fp) {
    MessageBox(NULL, "Can't execute process", "Info", MB_OK);
    exit(1);
  }

  ofp = fopen("output.txt", "w");
  if (!ofp) {
    MessageBox(NULL, "Can't open output file", "Info", MB_OK);
    exit(1);
  }
  
  while (fgets(buf, sizeof buf, ifp))
    fputs(buf, ofp);

  close(fp);
  close(ofp);

  MessageBox(NULL, "Done", "Infomation", MB_OK);
  
  return 0;
}
補足コメント
goku3

お礼率 78% (97/123)

ありがとうございます。
ご提示のソース内容のようなことを私もやってみました。
その際に、
 ifp = _popen(cmd, "r");
 if (!fp) {
    MessageBox(NULL, "Can't execute process", "Info", MB_OK);
    exit(1);
 }
ここで、fp==NULLの動作になってしまいます。

※【重要】
あと、
私自身、質問の初っ端で、VC++(Console Appli)と自ら書いていながら、
実際には、実行すると簡単なダイアログウィンドウを表示し、
内部的にも、OnOK()やら、OnCancel()などの制御をしていました。
余計なお手間もお掛けし、申し訳ありませんでした。
投稿日時:2006/07/20 14:54
  • 回答No.1

ベストアンサー率 62% (800/1280)

コマンドの出力を受け取りたいということなら、popen (_popen)を使ってみてはどうでしょう?
多分コンソールも出てこないと思います。
補足コメント
goku3

お礼率 78% (97/123)

ご回答ありがとうございました。
popen()というようなi/fがあったのですね。従来からなんでもsystem()でファイルリダイレクトさせて対応していました・・・

それで、_popenを試してみたのですが、どうしてもNULLしか返してきません。
ヘルプを見ると、
『メモ _popen 関数を Windows プログラムで使用すると、無効なファイルハンドルを返し、プログラムがハングアップする原因となります。』
に関連しているようにも思います。

creating_a_child_process_with_redirected_input_and_output
に関して、調べてみたいと思います。
投稿日時:2006/07/20 11:01
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ