C++からはじめたので、パイプについてよくわかりません。
DOSで
dir | more
とか、UNIXで
ls | more
とかやると、前のコマンドの標準出力を、後ろのコマンドの標準入力に渡すというのは、わかるんですが、これはDOS上、UNIX上でのことですよね。
プログラムToプログラムで、パイプを使うには、どうしたらよいのでしょうか。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

Windowsのパイプって名前つきパイプですよね。


多少“うろ覚え”が入ってますが、参考になれば…。

まず、「名前つきパイプはNT系のみのサポート」という前提があります。
9x系では使えませんので御注意下さい。
また、名前つきパイプを実現するのはAPI呼び出しの組み合わせです。
VBからでも、C++からでも、その組み合わせ(片方がVBで他方がC++)でも可能です。

Windowsの名前つきパイプはUnixのそれとは異なり、サーバーとクライアントという位置付けで構成されます。
サーバーはCreateNamedPipeで名前つきパイプを作成します。
作成された名前つきパイプに対するアクセスは(指定によって)サーバー→クライアント、サーバー←クライアント、サーバー←→クライアントのいずれかのアクセスが可能となります。

名前つきパイプはサーバー/クライアント双方でCreateFileすれば通常ファイルと同様にReadFile、WriteFileが可能です。

概念的には「サーバーが用意した“名前つきパイプオブジェクト”を仮想ファイルとしてI/Oし通信を実現する」という感じです。

MSDNライブラリでpipe、named pipe、CreateNamedPipe、CreateFileを調べてみてください。
    • good
    • 0
この回答へのお礼

\\.\pipe\pipename
というファイルを出力側が用意し、受け取り側がそのファイルを開いて読み取るということになるのでしょうか。

うーむ、でもNT系にしか対応していないんですよね。
ソケットを使うといいのでしょうか。
ソケットもよくわからないのですが・・・。

何か、普通のコマンドライン引数のように、互いのプログラムが何か固有の値を知っていなければ、情報を交換できないようなもの、でないような、アプリケーション通信手段はないでしょうか。
名前とかIPとかが必要ないような。
相互通信である必要はありません。

お礼日時:2001/06/01 14:40

こんにちは、honiyonです。


 http://www.google.com/search?q=CreateFile+%83p%8 …

 上記「CreateFile パイプ」での検索結果です。
 ちょっと時間がないので詳しくは調べてないのですが、軽く見た感じそれの文献がヒットしているようです。

 VC++で作ったAPIをVBで使用したいというのは、VC++で作った関数を VBで使いたいと解釈して宜しいですか? それでしたらパイプとはまた違った事になると思います。
 VC++で作った関数をDLL化し、VBからその関数をロードする、という方が適切かと思います。 

 参考になれば幸いです(..
    • good
    • 0
この回答へのお礼

MSDNライブラリは見たのですが、パイプに対する知識があまりないので、これを見ただけではわかりませんでした。

具体的にやりたいことは、アプリケーションが渡す引数の変わりに、パイプを使いたいと思ったのです。
コマンドライン引数は文字制限があるので。
パイプ付きでアプリケーションを実行し、VB用にCommand$関数のようなものを作って・・・。

お礼日時:2001/06/01 14:28

DOSのパイプはリダイレクトを拡張したもので、前段プロセスがファイルに吐き出した標準出力を後段プロセスが標準入力とします。


結果、前段プロセスの終了をまって後段プロセスが起動します。
これはシングルタスクであるDOSの宿命です。

UNIX(Linuxを含む)のパイプは名前つき、名前なしの2種類があり、shellコマンドで実行可能な|は名前なしパイプです。
UNIXはマルチタスクなので前段プロセスと後段プロセスは同時に実行され、バッファリング単位(標準入出力ではBUFSIZまたは'\n'まで)ごとにデータが流れます。

UNIXを例にとります。
(DOSでも同様なライブラリ関数が用意されますが、上記の理由で動作は全く違います。また、細かな仕様も違うので確認して下さい)

<親プロセスが前段、後段プロセスを起動する場合>
Shellのやっている事と同じです。
1.親プロセスでpipe(2)システムコールを呼び出してパイプを作成
2.fork(2)システムコールで前段プロセスを生成
3.前段プロセスの標準出力をclose(2)
4.前段プロセスでパイプ出力側をdup(2)して標準出力とする
5.後段プロセスをfork(2)
6.後段プロセスで標準入力をclose(2)
7.後段プロセスでパイプ入力側をdup(2)して標準入力とする
8.前段、後段プロセスをexec(2)

前段/後段プロセスに当たるプログラムでパイプを意識したプログラミングがなされている場合、標準入出力のclose(2)とdup(2)は不要です。
名前つきパイプも使えます。

<子プロセスからの出力を受け取る場合>
1.pipe(2)でパイプを生成する
2.fork(2)で子プロセスを生成する
3.子プロセスで標準出力をclose(2)
4.子プロセスでパイプの出力側をdup(2)
5.子プロセスを目的のプログラムにexec(2)

この手順を単純化したライブラリ関数がpopen(3)です。
子プロセスに当たるプログラムがパイプを意識したプログラムの場合、標準出力のclose(2)とdup(2)は必要ありません。

詳しくはman(1)コマンドで各システムコールを調べてください。
()の中の数字はマニュアルの章番号でmanコマンドの第2パラメータです。
man 2 pipe
のように使ってください。


以上の説明は、4.3BSD,SystemV Rel3.1以降の全てのUNIX(Linux含む)で通用するはずです。

老婆心ながら…
UNIXならプロセス間通信にパイプを使うのは推奨されません。
プロセス間通信はメッセージまたはUNIXドメインソケット()を使います。

この回答への補足

書き損じました、すみません。
目的のプラットフォームはWinなのです。

・・・でも、Win上でもpopenはあるようですね。
Winプログラムでは正しく動作しないようですが。

popenは呼び出したプロセスからの出力を受け取るようですが、呼び出したプロセスに出力を与えるという動作はできないのでしょうか。

APIのCreateFileがパイプを作れるようですが、どのように扱えばいいのかわかりません。
このハンドルはCのpipe関数の返すものと方が違うようです。

補足日時:2001/05/29 15:06
    • good
    • 0

こんにちは、honiyonです。



 Linuxであれば、 popenを使うとプログラム同士でファイル入出力間隔で通信が出来ます。
 popenで、「ls」を開いてあげると、lsを実行した結果をもらえる、といった感じです。

 

この回答への補足

Win上ではムリでしょうかね。
具体的にはC++でAPIを作って、VBに使わせるということをしたいのですが。

補足日時:2001/05/29 15:04
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QUNIXの"find"コマンド同等のプログラム作成について

お世話になっております。
現在UNIXの"-type f"オプションのついた"find"コマンドと同等のプログラムをC言語で作ろうとしています。
つまりディレクトリ内のファイル(サブディレクトリ内のファイル含む、ディレクトリは除外)を全てフルパスで表示するプログラムです。
現在下記の関数を作成したのですがうまく動いてくれません。
どなたかご教授いただけないでしょうか。

【問題】
プログラム内の(**)前後で"dir1"が変更される。
(**)前:"/ディレクトリA/"
(**)後:"/ディレクトリA/ディレクトリA内のファイル1"
本当は"dir1"には:"/ディレクトリA/"のままであってほしいです。
"strcat"コマンドの仕様が影響しているのでしょうか。

int _find(char dir1[] , int k ,int l , int m )
{
DIR *dir ;
struct dirent *dp ;
struct stat statbuf ;
char txt[1000] ;
if ( m == 0 ) l++ ;
if ( (dir = opendir(dir1)) == NULL ){
printf("%s",dir1) ;
perror("opendir") ;
exit(1) ;
}
for( dp=readdir(dir) ; dp != NULL ; dp=readdir(dir) ){
if ( strcmp(dp->d_name,".") != 0 && strcmp(dp->d_name,"..") != 0 ){
/* ROOT_DIR名-にファイル名を付け加えて、フルパスにする */
strcpy( temp[k][l] , dir1) ;
strcat( temp[k][l] , "/" ) ;
strcat( temp[k][l] , dp->d_name ) ;  (**)
stat( temp[k][l] , &statbuf ) ;

if(S_ISDIR(statbuf.st_mode)){
l=_find(temp[k][l],k,l,1) ;
}else{
sort[k][l]=temp[k][l] ;
printf("temp[%d][%d]=%s\n",k,l,sort[k][l]);
printf( "dir5=%s\n",dir1) ;
l++ ;
}
}
}
closedir(dir) ;
return l ;
}

お世話になっております。
現在UNIXの"-type f"オプションのついた"find"コマンドと同等のプログラムをC言語で作ろうとしています。
つまりディレクトリ内のファイル(サブディレクトリ内のファイル含む、ディレクトリは除外)を全てフルパスで表示するプログラムです。
現在下記の関数を作成したのですがうまく動いてくれません。
どなたかご教授いただけないでしょうか。

【問題】
プログラム内の(**)前後で"dir1"が変更される。
(**)前:"/ディレクトリA/"
(**)後:"/ディレクトリA/ディレ...続きを読む

Aベストアンサー

以下のようにして下さい。
int _find(char dir1[] , int k ,int l , int m )
の中で、
(1)char temp_dir[256];を宣言する。
(2)
if(S_ISDIR(statbuf.st_mode)){
l=_find(temp[k][l],k,l,1) ;
}else{

l=_find(temp[k][l],k,l,1) ;を
strcpy(temp_dir,temp[k][l]);
l=_find(temp_dir,k,l,1) ;
上記の2行に置き換える。
temp[k][l]で渡されたのを、dir1で受け取りますが、
その後、temp[k][l]へファイル名をセットしているため、
dir1自体が同じ領域なので、結果的にdir1が破壊されたように見えます。これを防ぐには、一旦、temp_dirの格納し、それをdir1として渡します。

QDOS上でTCP通信を行うプログラムの作成

DOS上でTCP通信を行うプログラムを作成する必要が出てきましたが、どのように作成すればよいかわからない状態です。

動作環境としては、DOS上にLanManagerをインストールしたPCで、コンパイラは、MS-C7.0です。

WindowsではWinSockを使用したプログラミングの経験はありますが、DOSではどのように行えばよいかわかりません。

ライブラリなどが必要と思うのですが、フリーのライブラリなどがあるのでしょうか。

何か情報があれば教えてください。

Aベストアンサー

趣味も合わせて実務経験からご回答申し上げます。

まず必要なのは、パケットドライバというものです。
むかし、通常パケットドライバはネットワークカード製品についていたものですが、3ComやIntelは別途配布する形でしたのでネットワークカード製品には付いていません。
最近はDOSベースで使うユーザーも少ないためか日本国内ではパケットドライバの入手は困難です。
PC98とかだと更に難しいです。

PC/AT互換機やDOS/Vなら、

幸いなことに、
古くから良く知られているダウンロードサイトで

http://www.simtel.net/

があります(英語)。
日本には無いとてつもなく大きなサイトで、DOSでもMacでもOS-9でも何でもあります。
ここで半角英字キーワード「packet driver」で検索してください。

例)
・3c509a.zip - 3c509 (Etherlink III) packet driver, v10.1
・exp16104.zip - Intel EtherExpress 16 packet driver for new TP
 などがあります。

自分の環境に合ったネットワークドライバがどうしてもほしいときは

 http://www.network-drivers.com/

から検索してください(これも英語)。
世界中のネットワークカードが検索できて、対応していればDOS用のパケットドライバを手に入れることができます。

DOS上でTCP/IPをアプリとして使うだけなら、DOSPPPというものを使えばメールやブラウザを使用できます。
simtel.net 等のダウンロードサイトで「DOSPPP」で検索すればその手のプログラムが探し出せます。


◆プログラミングについて

パケットドライバは最下位のレイヤーに相当するので、プログラミングは、基本的にはアセンブラでコーディングします。
パケットドライバはプロトコルスタックを実装しています。操作は、このプロトコルスタックと呼ばれる部分の操作が大半になります。
TCP/IPを使うなら、TCP/IPスタックですね。稀にドライバによっては含んでいないこともあるので注意してください。

WinSock等はいわゆる、このプロトコルスタックを操作するライブラリなのですが現在はフリーソフトではなくなったため使えません。(フリーソフトだったのは20年以上も前の話です ^^;)

基本的に、どのメーカーのパケットドライバでもNovell-NE2000用に書かれたプログラムは必ず動作します。つまり、このNE2000用のプログラムを作ればいいわけです。

プログラムを作るには、このパケットドライバを呼び出します。いくつかのパケットドライバを落としてくると、中にはサンプルのプログラムとかが入っています。この辺を参照しながら作ってゆくと幸せになれるかもしれません。

環境の構築方法についてはもっと詳しい方法が、
Googleで「パケットドライバ 使い方」等で引いてみると出てきます。

お役に立ちましたら幸いです。

趣味も合わせて実務経験からご回答申し上げます。

まず必要なのは、パケットドライバというものです。
むかし、通常パケットドライバはネットワークカード製品についていたものですが、3ComやIntelは別途配布する形でしたのでネットワークカード製品には付いていません。
最近はDOSベースで使うユーザーも少ないためか日本国内ではパケットドライバの入手は困難です。
PC98とかだと更に難しいです。

PC/AT互換機やDOS/Vなら、

幸いなことに、
古くから良く知られているダウンロードサ...続きを読む

QC++ で DIR コマンド

MS-DOSプロンプトで dir と入力すれば、フォルダ内の
様子がMS-DOSプロンプトに表示されるけど、
C++ で、MS-DOSプロンプトで dir と入力したのと同じ
様にするにはどういうプログラムを作ればいいのですか?
別の言い方で書くと、実行すればMS-DOSプロンプトが
起動し、dir と入力されて dirコマンドが実行される
というファイルを作るソースが知りたいんです。
dirコマンドが実行される対象となるディレクトリは
どこでもいいんです。
C++ のプログラムでも、ディレクトリ構造を出力することが
出来ると思うんだけど、MS-DOSプロンプトでやってみたいんです。
どうしてそんなことがしたいのかというと、C++ が難しそうだから
という理由なんです。
例えば、ファイルコピーを自動化するプログラムを作る時、
C++ のプログラムの出力をMS-DOSプロンプトへ渡す方法を知っていれば、
MS-DOSプロンプトでのコピーは copy コピー元 コピー先
という簡単な書式だから、ファイルコピーを自動化するプログラムも
簡単に作れそうだなと思ったんです。

MS-DOSプロンプトで dir と入力すれば、フォルダ内の
様子がMS-DOSプロンプトに表示されるけど、
C++ で、MS-DOSプロンプトで dir と入力したのと同じ
様にするにはどういうプログラムを作ればいいのですか?
別の言い方で書くと、実行すればMS-DOSプロンプトが
起動し、dir と入力されて dirコマンドが実行される
というファイルを作るソースが知りたいんです。
dirコマンドが実行される対象となるディレクトリは
どこでもいいんです。
C++ のプログラムでも、ディレクトリ構造を出力することが
出来る...続きを読む

Aベストアンサー

Borland系であれば、

#include <stdlib.h>
#include <cstring.h>
int main(int, char** argv)
{
*argv++; // まず自分のプログラム名はパス
// 後々の独自の拡張を考えてMemcopy などは使わない
string s="dir ";
while (*argv) {
s += *argv++;
s += ' ';
}

system(s.c_str());
return 0;
}

#include <cstring.h>

#include <string>
が現在は本流。

QUNIX上でdos.hをインクルード

下記のURLのプログラムらをUNIX(Solaris)上でコンパイルするとdos.hファイルが見つからない,というようなエラーが出ます。これらのプログラムをSolaris上でコンパイルし,実行できるようにするにはどう書き換えればよろしいのでしょうか。課題の一部なのですが宜しくお願いします。
http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/rec_key_points.c

http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/rec_angle.c

http://www-itolab.ics.nitech.ac.jp/creport/enshu_kadai/src/robot_simulator.c

Aベストアンサー

#1です。

>このcheck_point(a,b)はコメント扱いになっているのでしょうか。
そうですね。Cでは、/* から */ はコメントです。
これは、IBM-PC用のコードのようです。で、下のほうにある同じ関数が、
NEC PC-9801用のコードのようです。
(IBM-PC用のソースをPC-9801用に移植したものかもしれません)
機能としては、カーソル位置の文字が'*'かどうかを検査するものです。

>また,int86やregsとはなんなのでしょうか。
int86は、Pentiummのご先祖様の8086CPUのソフトウェア割り込みです。
今でもDOSモードで動くと思います。BIOSをCALLする時などに使用します。
(例では、IBM-PCのVIDEO BIOSである INT 10h を呼び出しています)

regsというのは、CPUのレジスタに値をセットするための共用体変数です。
regsにレジスタにセットしたい値をセットして、int86関数をCALLすると、
アセンブラで呼び出すようなことがCで可能になるのです。

サンプル(課題)のソースのコメントアウトされている方の関数(IBM-PC用)を
有効にして、下にある同じ関数名の方(PC-9801用)をコメントアウトして
DOS用のCコンパイラでコンパイル/リンクするとDOSプロンプトで実行できる
と思います。(PC-9801でない普通のWindowsマシンなら)

int86についてはこちらをご参考に。
http://www2.muroran-it.ac.jp/circle/mpc/old/pc98dos/dos/dosinit.html

フリーのDOS用のCコンパイラはこちらからダウンロードできます。
http://www.vector.co.jp/soft/maker/lsi/se001169.html

本題については、Solarisでこの機能(check_point()関数)をどう実現
するかということになろうかと思います。

参考URL:http://www2.muroran-it.ac.jp/circle/mpc/old/pc98dos/dos/dosinit.html

#1です。

>このcheck_point(a,b)はコメント扱いになっているのでしょうか。
そうですね。Cでは、/* から */ はコメントです。
これは、IBM-PC用のコードのようです。で、下のほうにある同じ関数が、
NEC PC-9801用のコードのようです。
(IBM-PC用のソースをPC-9801用に移植したものかもしれません)
機能としては、カーソル位置の文字が'*'かどうかを検査するものです。

>また,int86やregsとはなんなのでしょうか。
int86は、Pentiummのご先祖様の8086CPUのソフトウェア割り込みです。
今で...続きを読む

Qコマンドプロンプト画面で動作中のWin32プログラムに対して、他のプログラムから文字入力する方法

先に質問点を書きます。
1.Windowsでは、他の実行中のWindow(プログラム)にメッセージを送信して制御できるようですが、コマンドプロンプト画面にも送信できますか。
2.そういうツールご存じないですか。
3.Visual C のサンプルプログラムご存じないですか。
 (何もないと私には無理です。あっても無理かも・・・。)

長くなりますが、背景説明をします。
実行ファイル名は、用途が分かりやすいよう仮名にしてお訪ねします。

パソコンにUSB接続して使用するオシロスコープ装置を購入しました。
その添付ソフトのサンプルプログラムを改造して、MyPsCON.exeというWin32プログラムを作りました。
コマンドプロンプト画面で、このMyPsCON.exeを起動すると、信号入力がある度に電圧変化を読み取って、data.txtというファイルを書き出します。
作業を終了するときは、キーボードから「X」と1文字入力すると、装置がUSBセッション(?)をクローズして、パソコンのコマンドプロンプト画面が閉じます。

私は、上記MyPsCON.exeを、Windows版の自作プログラムMyPsWin.exeから起動(shell起動というんですか)しています。

次にやりたいことは、MyPsWin.exeからMyPsCON.exeに対して、任意の時点で「X」と文字入力してそのMyPsCON.exeを終了させたいのです。

MyPsCON.exeをバッチファイルで起動~終了まで一括動作させられますが、起動時には何回読取動作させるか分からないのでダメです。

そんな訳で、冒頭の質問になります。
winbatchという市販有料ソフトが目的に合いそうですが、これだけに使うには勿体ないです。

よろしくお願いします。

先に質問点を書きます。
1.Windowsでは、他の実行中のWindow(プログラム)にメッセージを送信して制御できるようですが、コマンドプロンプト画面にも送信できますか。
2.そういうツールご存じないですか。
3.Visual C のサンプルプログラムご存じないですか。
 (何もないと私には無理です。あっても無理かも・・・。)

長くなりますが、背景説明をします。
実行ファイル名は、用途が分かりやすいよう仮名にしてお訪ねします。

パソコンにUSB接続して使用するオシロスコープ装置を購入しました。
その添...続きを読む

Aベストアンサー

既存のプログラムを取り込むのがめんどくせー。ってのは判らんでもないですけどね……。

>SendMessageAPI関数は、コマンドプロンプトウィンドウで実行中のMyPsCON.exeに適用できるんでしょうか。

実行しているアプリに対しては適用できませんが、そのコマンド プロンプトのウィンドウへの適用は可能でしょう。
プログラムを実行しているコマンド プロンプトのウィンドウを検索するのが少々手間かも知れませんけど。

とりあえず、普通に起動しただけのコマンド プロンプトに対して、下記の処理で「a」が入力されたのは確認しました。
# Windows7 64BitにVC++2010Expressにて

 HWND hConsoleWnd = NULL;

 hConsoleWnd = FindWindowEx(NULL, NULL, TEXT("ConsoleWindowClass"), TEXT("管理者: コマンド プロンプト"));
 if(hConsoleWnd) {
  SendMessage(hConsoleWnd, WM_CHAR, (WPARAM)'a', (LPARAM)0);
 }

FindWindowEx()の第4引数が問題になる…かも知れませんな。
# 複数起動していたらどうなる?とか、FindWindowEx()からSendMessage()までの間にウィンドウ閉じられたら(普通は無理ですが)どうする?とか……。
ちなみに、第4引数の文字列はSpy++にて該当ウィンドウのプロパティから取得。
見た目だけだと半角スペースの数とか合わないかも知れないから。

既存のプログラムを取り込むのがめんどくせー。ってのは判らんでもないですけどね……。

>SendMessageAPI関数は、コマンドプロンプトウィンドウで実行中のMyPsCON.exeに適用できるんでしょうか。

実行しているアプリに対しては適用できませんが、そのコマンド プロンプトのウィンドウへの適用は可能でしょう。
プログラムを実行しているコマンド プロンプトのウィンドウを検索するのが少々手間かも知れませんけど。

とりあえず、普通に起動しただけのコマンド プロンプトに対して、下記の処理で「a」が入力された...続きを読む


人気Q&Aランキング

おすすめ情報