2011-12-24 184 views
4

我有一個啓動並執行一些工作的命令行應用程序。在那段時間裏,它監聽擊鍵(s =>顯示狀態)。這不是典型的命令提示符,你按's'並且<ENTER> - 這是一旦鍵被按下,狀態顯示就會作出反應的類型。將命令發送到無窗口命令行進程(從C#應用程序啓動)

現在我試圖通過發送擊鍵來控制來自花哨的GUI應用程序的命令行應用程序。我已經嘗試了寫入Process'StandardInput的更傳統的方法,但似乎沒有任何效果。另外,因爲實際進程沒有窗口(它以CreateNoWindow = true開始),所以我無法嘗試使用Win32 API將擊鍵發送到窗口。

有沒有其他方法可以做到這一點?

+4

是你寫的命令行應用程序一個(或至少具有源代碼)?如果是這樣,我會將你想要重用的位重構到GUI和命令行工具使用的單獨庫中。 – 2011-12-24 20:58:26

+0

您是否確定在使用Process'StandardInput時沖洗流? – jclozano 2011-12-24 21:00:04

+0

@JonSkeet:呵呵,如果我有奢侈的源代碼,我不會問這個問題:P我只是更改應用程序以更好地工作。 是的,我通過調用Flush()命令完成FLUSH流。沒有幫助。 – Iv4n 2011-12-24 21:24:42

回答

1

那麼,我似乎已經找到了我自己的問題的答案。 這是一個真正的「拼湊在一起」的解決方案,但它的工作原理 - 並且對於我正在構建的應用程序的所有意圖和目的而言,並不重要。

所以,我所做的是使用兩個名爲

static extern bool ShowWindow(IntPtr WindowHandle, int nCmdShow); 
static extern bool SetForegroundWindow(IntPtr WindowHandle); 

WinAPI的函數的第一個可用於顯示/分別改變的nCmdShow爲1和0隱藏的窗口。另一個將窗口(由WindowHandle決定)放在前面。將這兩者結合在一起,我可以通過編程方式將控制檯窗口提前,做一個簡單的SendKeys.Send();操作,然後再次隱藏它。現在

// Use a WIN API command to bring the command line to front 
SetForegroundWindow(workerProcess.MainWindowHandle); 
// Send a keystore to re-display the STATUS of the worker 
SendKeys.Send("s"); 
// Hide the window again. 
ShowWindow(workerProcess.MainWindowHandle, 0); 

,它是一個真正的雜牌組裝電腦的工作,但它能夠完成任務。一個潛在的缺陷是如果用戶正在使用計算機來處理其他事情,並且在窗口處於活動狀態並使用'q'時,將在10000000時刻指出1 - 它將退出工作程序。但該應用程序的目的是在專用機器上使用,這些機器很可能連監視器,鍵盤或鼠標都連接到它們上面,所以這不是問題。

感謝所有回答的人,因爲您以這樣或那樣的方式引導我走向正確的解決方案。

2

花式控制檯應用程序存在問題。

他們傾向於直接讀取鍵盤輸入,而不是通過stdin。他們也有直接控制他們的控制檯的傾向,而不是通過標準輸出。

AFAIK,沒有辦法以編程方式控制這些應用程序。如果你真的,真的需要,我會探討像AutoHotKey控制私人desktop(AHK使用虛擬鍵盤/鼠標驅動程序)上的應用程序。不過,我不確定你會如何從控制檯上讀取結果;它可能可以創建一個由程序啓動的中間控制檯應用程序(在私人桌面中)並啓動目標應用程序。中間應用程序然後將share its console與目標應用程序並使用low-level I/O來檢測更改。

或者您可以使用Detours來彎曲目標應用程序的意願。

+0

感謝您的回答。其實,我可以很容易地閱讀它。只發送輸入似乎是一個問題。我會檢查這兩件事情,看看它是否有效。編輯:很奇怪發送擊鍵(就好像它是在鍵盤上鍵入)不像標準寫作STDIN :) – Iv4n 2011-12-24 22:12:00

+1

實際上有軍備競賽。一方面是*真正*想要從真實*鍵盤讀取的應用程序,另一方面是*真正希望虛擬出這些應用程序的應用程序。 'WM_KEYUP' /'WM_KEYDOWN','keybd_event','SendInput'('SendKeys')等。我曾經承包編寫虛擬鍵盤驅動程序,因爲有一個程序完全拒絕虛擬化。在軍備競賽中,虛擬化總是贏得勝利。 :)直到使用TPM。 :( – 2011-12-24 22:41:19

1

我發現了一個更好的方法來完成功能,而沒有導致同時用戶輸入和窗口切換問題的理論風險。

訣竅是使用名爲PostMessage的WinAPI函數將KeyDown(或KeyUp)消息發送到執行相同操作的進程。無需將工藝窗口放在前面,然後立即將其隱藏起來!

我送鍵下命令鍵「S」作爲參數:

 // 0x0100 - VM_KEYDOWN 
     // 0x0101 - VM_KEYUP 
     // 0x53 - S-key 
     PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0); 
     PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0); 
+0

PostMessage?它來自哪裏? – 2017-07-14 05:58:43

+1

WinAPI函數 – Iv4n 2017-07-14 09:12:58