在Codeplex 上可以找到一个输入模拟器,它可以为您完成这项工作。
我正在编写一个示例代码,很快就会在这里发布,请记住输入模拟器类似于 Remus 提供的链接中的内容...
编辑:我发现这有一个限制,你绝对可以摆脱典型的System.Windows.Forms.SendKeys.Send 方法,它确实有效! ,但是,进程必须有
- 没有流的重定向
- 不能隐藏窗口(这是它会失败的地方,因为窗口的句柄无处可见,无法将其带到前台使其处于活动状态!)
- 一个窗口显示了这个过程是有效的!
在您的情况下,只需找到窗口,通过 pinvoke 'SetForegroundWindow' 将其设置为活动状态,然后发送序列^{BREAK} 将 Ctrl+Break 信号发送到运行良好的进程(特别是如果process 是一个命令行程序/批处理文件)。这是CodeProject 上的一篇文章,它完全做到了这一点并反映了 SendKeys...我还没有将一些代码粘贴到这里来演示......
Edit#2:其实我很惊讶...因为这段代码将显示(概念证明)...它正在使用:
- InputSimulator(如前所述)
- 由一个按钮组成的 windows 窗体,当窗体被加载时,它会自动运行该类。单击按钮后,它会向隐藏进程发布 ctrl-break
- 输出流确实被重定向并且是一个隐藏窗口。
- 奇怪的是,正在捕获输出,但不会在调试窗口中实时显示结果,也就是说,它被缓冲(我猜)直到进程终止,显示整个输出。 .
- 我在
FindWindow API 调用上作弊了一点,因为我知道窗口的标题曾经并且能够以某种方式将其带到前台,并使用 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”线程,我直接从主 GUI 线程调用了“PostCtrlC”方法......这是一个迂腐的概念验证代码,但它确实表明它需要实现“ISynchronizeInvoke”以使其成为线程安全的,除此之外......它确实有效。