На Codeplex найден симулятор ввода, который может выполнить только вашу работу.
Я работаю над примером кода и вскоре опубликую здесь, имейте в виду, что Симулятор ввода похож на то, что было найдено по ссылке, предоставленной Remus ...
Редактировать: Я обнаружил, что с этим есть ограничение, вы определенно можете обойтись без типичного System.Windows.Forms.SendKeys.Send
метода, он работает эффективно! , но процесс должен иметь
- Нет перенаправлений потоков
- Нельзя скрыть окно (это то место, где оно выйдет из строя, поскольку дескриптор окна нигде не виден, нет способа вывести его на передний план, чтобы сделать его активным!)
- Окно, показывающее процесс, чтобы это было эффективным!
В вашем случае нужно найти окно, установить его активным с помощью pinvoke 'SetForegroundWindow' и отправить последовательности ^{BREAK}
, которые посылают сигнал Ctrl + Break процессу, который работает очень хорошо (особенно если процесс - это командная строка программы / командного файла). Вот статья о CodeProject , которая делает это точно и отражает SendKeys ... Я еще не вставил в это код, чтобы продемонстрировать ....
Редактирование # 2: На самом деле я весьма удивлен ... как покажет этот код (подтверждение концепции) ... он использует:
- InputSimulator (как упоминалось ранее)
- Форма окна, состоящая из кнопки, при загрузке формы она автоматически запускает класс. После нажатия на кнопку он отправляет Ctrl-Break в скрытый процесс
- Выходной поток действительно перенаправлен и является скрытым окном.
- Странная вещь, это то, что вывод захватывается, но не показывает результаты в окне отладки, то есть в режиме реального времени он буферизуется (я полагаю), пока процесс не завершится, весь вывод будет показан .. .
- Я немного обманул вызов API
FindWindow
, потому что я знал, что заголовок окна был и каким-то образом мог вывести его на передний план и использовать InputSimulator для отправки на него нажатий клавиш ... или использовать традиционная простая старая функция SendKeys
... причина, по которой у меня была Thread.Sleep
, заключается в том, чтобы гарантировать, что нажатия клавиш отправляются для того, чтобы их "толкали в очередь клавиатуры" активного окна переднего плана ", которая, несмотря на это, скрыта «
- Я использовал команду 'netstat -e 5' для бесконечного цикла, обновляя результаты каждые 5 секунд, пока не получит Ctrl + C, чтобы разорвать бесконечный цикл.
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);
}
}
}
Кстати, я знаю, что netStat
выполняется из потока 'BackgroundWorker', и я напрямую вызвал метод 'PostCtrlC' из основного потока GUI ... это педантично как код для проверки концепции , но он показывает, что ему нужно реализовать ISynchronizeInvoke, чтобы сделать его поточно-ориентированным, за исключением ... он действительно работает.