System.Diagnostics.Process公開了一個名爲StandardInput的StreamWriter,它只接受字符,據我所知。如何將密鑰而不是字符發送到進程?
但是我還需要發送擊鍵以及一些擊鍵不能很好地映射到字符。
我該怎麼辦?
System.Diagnostics.Process公開了一個名爲StandardInput的StreamWriter,它只接受字符,據我所知。如何將密鑰而不是字符發送到進程?
但是我還需要發送擊鍵以及一些擊鍵不能很好地映射到字符。
我該怎麼辦?
你混合輸入流的控制信號。正如你已經知道的,控制檯進程有一個默認的輸入流,你可以用StandardInput控制它。但是,按Ctrl-C和Ctrl-中斷無法通過此流發送到進程的人物,而是他們是不是控制信號該進程接收使用已註冊的信號處理程序,請參見CTRL+C and CTRL+BREAK Signals:
默認情況下,當控制檯窗口具有鍵盤焦點時,CTRL + C或 CTRL + BREAK被視爲信號 (SIGINT或SIGBREAK)而不是 鍵盤輸入。
要發送假信號的過程中,你可以使用GenerateConsoleCtrlEvent
和發送任何CTRL_C_EVENT
或CTRL_BREAK_EVENT
。這個API沒有.Net等價物,所以你必須PInvoke它。
const int CTRL_C_EVENT = 0;
const int CTRL_BREAK_EVENT = 1;
[DllImport("kernel32.dll")]
static extern bool GenerateConsoleCtrlEvent(
uint dwCtrlEvent,
uint dwProcessGroupId);
http:// www。 google.com/codesearch/p?hl=zh-CN#ncfzeHH4QLA/pubs/consoledotnet/consoledotnet.zip%7CYrqh4ujA6zA/ConsoleDotNet/WinCon.cs – 2010-02-20 23:17:36
我正在使用FFmpeg屏幕錄製過程。這對我有用嗎?其實我想停止使用FFmpeg – Ahmad 2017-07-09 08:41:27
有一個輸入模擬器發現這裏Codeplex它可以爲你做只是工作:
從.NET你只需要包含函數定義中使用它。 我工作的一個示例代碼,將回到這裏後不久,牢記輸入模擬器是類似於在由瑞摩斯提供的鏈接找到...
編輯:我發現有這是一個限制,你一定可以擺脫典型的System.Windows.Forms.SendKeys.Send
方法,它確實有效!
,但過程必須有
在你的情況下,它發現窗口的問題,將其通過的PInvoke活躍「SetForegroundWindow」,併發送序列^{BREAK}
其發送CTRL + BREAK信號的過程,並很好地工作(特別是如果進程是命令行程序/批處理文件)。這裏有CodeProject,這是否準確,反映了...的SendKeys我還沒有粘貼一些代碼,這證明了一篇文章....
編輯#2:其實我很驚訝......作爲這個代碼將顯示(概念的證明)...它使用:
FindWindow
API調用中有點欺騙,因爲我知道窗口的標題是,並且以某種方式能夠將它帶到前臺,並使用InputSimulator將鍵擊發送給它......或使用傳統普通舊SendKeys
函數...我有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);
}
}
}
挑剔之外,我知道netStat
運行斷「的BackgroundWorker」線程,我直接調用從主界面線程的「PostCtrlC」的方法......這是迂腐的但它確實表明它需要實現'ISynchronizeInvoke'以使其線程安全,除此之外......它確實有效。
屏幕錄製的過程開始,但如果你有多個進程使用netstat。exe,那麼你會影響所有與PostCtrlC()?當你知道進程SessionId時,有沒有辦法做同樣的事情? – Constantin 2012-05-24 19:35:28
@Constantine代碼只能運行一個運行netstat.exe的窗口。您可以使用[EnumWindows](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633497(v = vs.85).aspx)並創建回調函數[EnumWindowsProc](http: //msdn.microsoft.com/en-us/library/windows/desktop/ms633498(v=vs.85).aspx)來獲取句柄並檢查它是否在該句柄的標題中有netstat.exe標題......如果找到它,然後將它帶入前臺,並將其作爲概念驗證代碼「zap」進行演示:) – t0mm13b 2012-05-28 22:59:59
哪些按鍵,例如? – 2010-02-16 17:05:56
@Rick退格,Ctrl + C – 2010-02-16 17:14:16
這是Unix管道抽象中的最終漏洞。重定向通過字符流發生,它不能模擬非鍵入的按鍵。 – 2010-02-16 17:33:48