Hay una entrada Simulador de encontrar aquí en Codeplex que puede hacer sólo el trabajo para usted. estoy trabajando en un código de ejemplo y se publicará de nuevo aquí en breve, tener en cuenta el simulador de entrada es similar a lo que se encontró en el enlace proporcionado por Remus ...
Editar: he encontrado que hay una limitación con esto, definitivamente puede salirse con la suya con el método típico System.Windows.Forms.SendKeys.Send
, ¡funciona de manera efectiva!
, pero, el proceso debe tener
- No hay cambios de dirección de las corrientes
- No se puede ventana oculta (aquí es donde se producirá un error, ya que el mango de la ventana es por ningún lado, no hay manera de llevarlo a el primer plano para hacerlo activo!)
- ¡Una ventana que muestra el proceso para que esto sea efectivo!
En su caso, es una cuestión de encontrar la ventana, la pusieron activa a través de PInvoke 'SetForegroundWindow', y enviar las secuencias ^{BREAK}
que envía la señal Ctrl + Pausa para el proceso que funciona muy bien (especialmente si el proceso es un programa de línea de comando/archivo por lotes). He aquí un artículo sobre CodeProject que hace esto exactamente y refleja la SendKeys ... todavía tengo que pegar un código en este para demostrar ....
Edición # 2: En realidad estoy bastante sorprendido ... como este código se mostrará (prueba de concepto) ... que está utilizando:
- InputSimulator (como se mencionó anteriormente)
- una forma de ventanas que consta de un botón, cuando el formulario se carga automáticamente ejecuta la clase . Al hacer clic en el botón, se publica un ctrl-break en el proceso oculto
- La secuencia de salida se redirige y es una ventana oculta.
- Lo extraño es que la salida se está capturando pero no muestra los resultados en la ventana de depuración, en tiempo real, es decir, se almacena en el búfer (supongo) hasta que finaliza el proceso, se muestra toda la salida. .
- Hice una trampa en la llamada a la API
FindWindow
, porque sabía que el título de la ventana era y de alguna manera era capaz de ponerlo en primer plano, y usar el InputSimulator para enviarle las teclas ... o usar el tradicional simple viejo SendKeys
función ... la razón por la que tuve el Thread.Sleep
es asegurar que las teclas se envían para ser 'empujadas a la cola del teclado de la' ventana activa de primer plano ', que a pesar de eso, está oculta'
- I usó el comando 'netstat -e 5' para repetir forev por ejemplo, actualizar los resultados cada 5 segundos hasta que reciba un 'Ctrl + C' para romper el ciclo infinito.
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 un lado, sé que el netStat
se está ejecutando el hilo 'BackgroundWorker', y yo invocado directamente el método 'PostCtrlC' desde el hilo principal interfaz gráfica de usuario ... esto es como un pedante código de prueba de concepto, pero muestra que necesita implementar 'ISynchronizeInvoke' para que sea seguro para subprocesos, aparte ... de hecho funciona.
¿Qué teclas presionadas, por ejemplo? –
@ Retroceso de retroceso, Ctrl + C –
Esa es la última fuga en la abstracción de tuberías Unix. La redirección ocurre a través de las secuencias de caracteres, no puede simular pulsaciones de tecla que no sean de tipeo. –