System.Diagnostics.Processは、StandardInputという名前のStreamWriterを公開します。これは、私が知る限り、文字のみを受け入れます。
ただし、キーストロークも送信する必要があり、一部のキーストロークは文字に適切にマッピングされません。
私は何をすべきか?
System.Diagnostics.Processは、StandardInputという名前のStreamWriterを公開します。これは、私が知る限り、文字のみを受け入れます。
ただし、キーストロークも送信する必要があり、一部のキーストロークは文字に適切にマッピングされません。
私は何をすべきか?
入力ストリームを制御信号と混合しています。すでにご存知のように、コンソールプロセスには、StandardInputで制御できるデフォルトの入力ストリームがあります。ただし、Ctrl-CおよびCtrl-Breakは、このストリームを介してプロセスに送信される文字ではなく、代わりに、登録されたシグナルハンドラーを使用してプロセスが受信する制御シグナルです。CTRL+CおよびCTRL+BREAKシグナルを参照してください。
デフォルトでは、コンソールウィンドウにキーボードフォーカスがある場合、CTRL+CまたはCTRL+BREAKは、キーボード入力としてではなく、信号(SIGINTまたはSIGBREAK)として扱われます。
偽の信号をプロセスに送信するには、またはのいずれかを使用しGenerateConsoleCtrlEvent
て送信できます。このAPIには.Netに相当するものがないため、PInvokeする必要があります。CTRL_C_EVENT
CTRL_BREAK_EVENT
.NETから使用するには、関数定義を含める必要があります。
const int CTRL_C_EVENT = 0;
const int CTRL_BREAK_EVENT = 1;
[DllImport("kernel32.dll")]
static extern bool GenerateConsoleCtrlEvent(
uint dwCtrlEvent,
uint dwProcessGroupId);
ここCodeplexに入力シミュレーターがあります。これはあなたにぴったりの仕事をするかもしれません。私はサンプルコードに取り組んでおり、まもなくここに投稿します。入力シミュレーターは、Remusが提供するリンクで見つかったものと似ていることに注意してください...
編集:System.Windows.Forms.SendKeys.Send
これには制限があることがわかりました。通常の方法で確実に回避できます。効果的に機能します。、しかし、プロセスは持っている必要があります
あなたの場合、それはウィンドウを見つけて、pinvoke'SetForegroundWindow'を介してアクティブに設定し^{BREAK}
、Ctrl + Break信号を送信するシーケンスを非常にうまく機能するプロセスに送信することです(特にプロセスがコマンドラインプログラムの場合) /バッチファイル)。これは、これを正確に実行し、SendKeysを反映するCodeProjectに関する記事です...これを示すために、まだいくつかのコードを貼り付けていません...。
編集#2:実際、私は非常に驚いています...このコードが示すように(概念実証)...使用しています:
FindWindow
ウィンドウのタイトルが前面に表示され、InputSimulatorを使用してキーストロークを送信できること、または従来の単純な古いSendKeys
関数を使用できることを知っていたので、API呼び出しを少しだましました。 。私が持っていた理由Thread.Sleep
は、「アクティブなフォアグラウンドウィンドウ」のキーボードキューにプッシュされるためにキーストロークが送信されることを確認するためです。public partial class Form1 : Form
{
private TestNetStat netStat = new TestNetStat();
public Form1()
{
InitializeComponent();
using (BackgroundWorker bgWorker = new BackgroundWorker())
{
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
bgWorker.RunWorkerAsync();
}
}
void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("BGWORKER ENDED!");
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
netStat.Run();
}
void btnPost_Click(object sender, EventArgs e)
{
netStat.PostCtrlC();
System.Diagnostics.Debug.WriteLine(string.Format("[{0}] - {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), this.netStat.OutputData.Replace(Environment.NewLine, "")));
}
}
public class TestNetStat
{
private StringBuilder sbRedirectedOutput = new StringBuilder();
//
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32")]
public static extern int SetForegroundWindow(IntPtr hwnd);
public string OutputData
{
get { return this.sbRedirectedOutput.ToString(); }
}
public void PostCtrlC()
{
IntPtr ptr = FindWindow(null, @"C:\Windows\System32\netstat.exe");
if (ptr != null)
{
SetForegroundWindow(ptr);
Thread.Sleep(1000);
WindowsInput.InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.CANCEL);
// SendKeys.Send("^{BREAK}");
Thread.Sleep(1000);
}
}
public void Run()
{
System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo();
ps.FileName = "netstat";
ps.ErrorDialog = false;
ps.Arguments = "-e 5";
ps.CreateNoWindow = true;
ps.UseShellExecute = false;
ps.RedirectStandardOutput = true;
ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
{
proc.StartInfo = ps;
proc.EnableRaisingEvents = true;
proc.Exited += new EventHandler(proc_Exited);
proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived);
proc.Start();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
}
void proc_Exited(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended");
}
void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
if (e.Data != null)
{
this.sbRedirectedOutput.Append(e.Data + Environment.NewLine);
System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data);
}
}
}
Nitpickyはさておき、が「BackgroundWorker」スレッドから実行されていることを知っていnetStat
ます。メインのGUIスレッドから「PostCtrlC」メソッドを直接呼び出しました...これは概念実証コードとしては衒学的ですが、それはスレッドセーフにするために「ISynchronizeInvoke」を実装する必要がありますが、それはさておき...実際に機能します。
この素晴らしいツール-AutoItを見たことがありますか。これはスクリプトツールです。バックスペースを送信するには、Send("{BACKSPACE}")
これは優れたツールであり、多くの手動クリック/ダブルクリックなどを自動化するのに役立ちます。
これはあなたの質問に関連していますか?
キーを送信できるWindowsフォームウィンドウがある場合は、SendKeysが適切なソリューションである可能性があります。
バックスペースとCtrl+Cを押す場合は、次のようになります。
SendKeys.Send("{BACKSPACE}^C");