2011-12-24 9 views
4

私は起動して何らかの作業をするコマンドラインアプリケーションを持っています。その間、キーストロークを聞きます(s => show status)。 's'を押す典型的なコマンドプロンプトではなく、<ENTER> - これは、キーが押されるとすぐに反応するタイプで、ステータスが表示されます。ウィンドウレスコマンドラインプロセスへのコマンドの送信(C#アプリケーションから開始)

今、私は、キーストロークを送信して、派手なGUIアプリケーションからコマンドラインアプリケーションを「制御」しようとしています。私はProcess 'StandardInputに書き込むより従来のアプローチを試みましたが、それはまったく効果がないようです。また、実際のプロセスにはウィンドウがありません(CreateNoWindow = trueで開始されています)、ウィンドウにキーストロークを送信するためのWin32 APIを試すことはできません。

他の方法はありますか?

+4

は、あなたが書いた(あるいは、少なくともソースコードへのを持っている)コマンドラインアプリケーション1ですか?もしそうなら、私はGUIとコマンドラインツールの両方が使用する別のライブラリに再利用したいビットをリファクタリングします。 –

+0

Process'StandardInputを使用しているときにストリームを確実にフラッシュしましたか? – jclozano

+0

@JonSkeet:私は、ソースコードの贅沢を持っていた場合ふむ、私は質問をされない:P私はちょうど良く動作するようにアプリケーションを変更したいです。 はええ、私はフラッシュ()コマンドを呼び出すことにより、ストリームをフラッシュしました。助けてくれなかった。 – Iv4n

答えて

1

私は自分の質問に対する答えを見つけたようです。 これは実際の「一体型」ソリューションですが、機能します。アプリケーションの目的や目的に合わせて、問題はありません。

だから、私がやったことは

static extern bool ShowWindow(IntPtr WindowHandle, int nCmdShow); 
static extern bool SetForegroundWindow(IntPtr WindowHandle); 

と呼ばれる2つのWinAPIの関数を使用する最初のものは、それぞれ、1/0にnCmdShowを変更することで、ウィンドウを隠すために使用することができました。もう1人はウィンドウ(WindowHandleで決定)を前面に置きます。これらの2つを組み合わせることで、私はプログラムでコンソールウィンドウを前面に持ってきて、簡単なSendKeys.Send()を実行できました。操作を行い、再度非表示にします。

今、それは本当のkludgeの仕事ですが、それは仕事を完了します。 1つの潜在的な落とし穴は、ユーザーがコンピュータを何か他のもののために使用していて、ウィンドウが 'q'でアクティブになっている10000000の瞬間にその1を釘付けにする場合です - ワーカープログラムを終了します。しかし、このアプリケーションは、モニタ、キーボード、またはマウスが接続されていない可能性が最も高い専用マシンで使用されるように設計されているため、問題にはなりません。

答えた人のおかげで、あなたが何らかの方法で正しいソリューションに向かって私を助けてくれたからです。

2

ファンシーコンソールアプリケーションに問題があります。

標準入力を経由するのではなく、キーボード入力を直接読み取る傾向があります。彼らはまた、stdoutを経由するのではなく、コンソールを直接制御する傾向があります。

AFAIK、これらのアプリケーションをプログラムで制御する方法はありません。本当にが本当にになる必要がある場合はのようなアプリをプライベートdesktop(AHKは仮想キーボード/マウスドライバを使用しています)で制御してみてください。私はあなたがコンソールから結果をどのように読むのかは分かりませんが、それはかもしれないあなたのプログラム(プライベートデスクトップ)で起動し、ターゲットアプリケーションを開始する中間コンソールアプリケーションを作成することは可能である。中間アプリケーションはshare its consoleとターゲットアプリを使用し、low-level I/Oを使用して変更を検出します。

Detoursを使用すると、ターゲットアプリを自分の意志に合わせて曲げることができます。

+0

答えをありがとう。実際、私はそれを簡単に読むことができます。入力を送信するだけで問題があるようです。私はそれらの2つの事をチェックし、それが機能するかどうかを見ます。 EDIT:(それはキーボードでタイプされたかのように)キーストロークを送信することはSTDINへの書き込みなどなど、標準ではないことをかなり奇妙な:) – Iv4n

+1

軍拡競争は、実際に、あります。一方の側には本当に*本物の*キーボードから読みたいアプリがあり、もう一方の側には本当に*それらのアプリを偽造したいアプリがあります。 'WM_KEYUP' /' WM_KEYDOWN'、 'keybd_event'、' SendInput'( 'SendKeys')、などが私は一度だけで仮想化することを拒否したプログラムがあったため、仮想キーボードドライバを書くために契約しました。軍拡競争では、仮想化は常に勝ちます。 :) TPMが使用されるまで。 : –

1

ユーザーの同時入力とウィンドウ切り替えで問題が発生するという理論的なリスクがなくても、機能を達成するためのさらに優れた方法が見つかりました。

トリックは、同じことをプロセスにメッセージをKeyDownイベント(またはkeyUpイベント)をアップ送信するためのPostMessageと呼ばれるWinAPIの関数を使用することです。プロセスウィンドウを前面に持ってきてすぐに隠す必要はありません!

私は、引数としてキー「S」でキーダウンコマンドを送信しています:

 // 0x0100 - VM_KEYDOWN 
     // 0x0101 - VM_KEYUP 
     // 0x53 - S-key 
     PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0); 
     PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0); 
+0

PostMessage?どこから来たのですか? –

+1

WinAPI関数 – Iv4n