質問: VisualBasic(.NetFramework4.0)Windows10でプログラミングをしております。 system.diagnostics.process.startでDOSプロンプト(CMD.EXE)を起動しその画面に表示されているテキストを取得(範囲選択&コピーでクリップボード保存)したく思いますが、WindowsAPIでどのような関数を使用すれば良いのか検討が付きません。 起動したプロセスから取得したMainWindowHandleを対象とした、もしくは引数に取る関数ではないかと想像しているのですがご存知の方おられましたらお助けお願いできますでしょうか? よろしくお願いします。
回答: まず、テキストをどう保持してどう描画するかはアプリケーションによって様々ですから、「ウィンドウハンドルを渡せばウィンドウに表示されているテキストを取り出せる」といった汎用的なAPIは存在しません。 cmd.exe をはじめとするコンソールアプリケーションの場合、例のウィンドウはWindowsが管理しているのでコンソールに表示されている文字を読み取るAPIもあります。ただし「現在のプロセスのコンソールウィンドウから読み取る」という形になるので、 * `AttachConsole()` で対象のプロセス(cmd.exeなど)のコンソールウィンドウにアタッチし、 * `GetStdHandle()` でスクリーンバッファのハンドルを取得し、 * `GetConsoleScreenBufferInfo()` でスクリーンバッファの大きさを調べ、 * `ReadConsoleOutputCharacter()` で任意の範囲の文字を読み取る という流れになります。別のプロセスから読み取る際には `FreeConsole()` で切り離したうえで、上記と同じことを繰り返します。 参考: コンソールへのアタッチ - EternalWindows ただこの場合、出力されたという通知は受けられないので定期的に確認する必要がありますし、どこからどこまでが新しい出力なのかも自分で判別する必要があります。改行と折り返しの区別もつきません。 「ボタンを押したらその時点での画面を取り込む」程度ならいいかもしれませんが、次のようなことをしたいなら標準入出力のリダイレクトの方が簡単かと思います。 * 自作のアプリからコンソールアプリとやり取りしたい ⇒ `process.StandardInput` に書き込んで `process.StandardOutput` から読みだす * やり取りが画面に表示されるようにしたい ⇒ `StandardInput` `StandardOutput` を通る内容をテキストボックスなどに表示する * ユーザーがコマンドを打てるようにしたい ⇒ テキストボックスにでも入力させて、 `StandardInput` に書き込む (コンソールAPIを直接叩くアプリや、出力がリダイレクトされているかどうかで挙動を変えるアプリの場合は別ですが。)