長期以來,我試圖在計算機啓動時自動執行一些操作。我以爲我會編寫一個C#控制檯應用程序來執行此操作,然後將其添加到Windows中的計劃任務以在啓動時執行。我的問題是一個程序,它需要一個密碼,並沒有選擇通過命令行打開。因此必須手動輸入。我的想法是從KeePass數據庫中檢索我的密碼,並使用SendKeys輸入密碼並登錄到程序。我遇到的問題是加載所需的時間;我無法檢測GUI界面何時加載並準備好用於SendKeys。有什麼方法可以檢測到這個?我假設我所需要的是「Process」類,因爲那是我用來運行程序的。還要注意,當我使用Process.Start()運行可執行文件時,程序會創建另一個登錄進程,但它沒有關聯的窗口,我可以使用Windows API調用看到。C#SendKeys在發送之前等待程序加載
好了,這是很長,我可以重新蓋...
問題: 從C#當第三方程序加載檢測(即啓動畫面消失了,GUI準備用戶交互 - 意義如果Process正在運行,我不能只依靠它)。 此外,第三方程序沒有命令行選項,或者我只是將它作爲參數運行密碼。
目標: 要使用SendKeys來自動輸入密碼,但我的程序必須等待第三方應用程序完成加載。
注: 使用C#.NET 3.5的控制檯應用程序 未檢測出負載爲我自己的形式,而是第三方,否則這將是容易的(即form_loaded事件...)
謝謝你看我的問題,如果你想了解更多細節或任何事情,請告訴我。
UPDATE:
問題解決了! 我收到的兩個答案合起來給我我想要的解決方案。所以如果任何人稍後會遇到這個問題,這就是我所做的工作。
所以這個程序自動登錄一些你必須登錄的客戶端軟件。我的問題是,該軟件沒有提供許多其他程序提供的命令行參數的選項或文檔,因此您可以使用密鑰文件或其他東西登錄。該程序還禁用了複製和粘貼功能,因此需要手動輸入密碼HAS,如果您像我一樣使用密碼,那麼這是一個很大的麻煩,複雜的密碼無法使用。所以我寫了這個程序,爲了我的利益以及其他人的工作;我只是安排它在登錄到我的Windows機器時運行,它會打開客戶端軟件並自動執行登錄。
//
// IMPORTANT Windows API imports....
//
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint procId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
// When I get to this point in my code, I already had the password and window title...
string password = "password";
string title = "window title";
// This gets a handle to the window I want where "title" is the text in the title
// bar of the window as a string.
// This is a Windows API function that must be imported by DLLImport
// I had to get the handle this way because all I knew about the third party
// window was the title, not the process name or anything...
IntPtr hWnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, title);
// Now that I have a handle to the login window I used another windows API
// call to get the process ID.
// This windows API call gives me the Process ID as an out parameter and returns
// the thread ID of the window. I don't use the thread it, but maybe you can...
uint loginWindowProcId;
uint loginWindowThreadId = GetWindowThreadProcessId(hWnd, out loginWindowProcId);
// now I can just use .NET to find the Process for me...
Process loginWindowProcess = null;
if (0 != loginWindowProcId)
{
// get the process object
loginWindowProcess = Process.GetProcessById((int)loginWindowProcId);
// This right here is why I wanted the Process structure. It takes a
// little while for the client software to load and be ready. So here
// you wait for the window to be idle so you know it has loaded and can
// receive user input, or in this case keys from "SendKeys".
loginWindowProcess.WaitForInputIdle();
// I use yet another windows API call to make sure that the login window
// is currently in the foreground. This ensures that the keys are sent
// to the right window. Use the handle that we started with.
SetForegroundWindow(hWnd);
// Now send the password to the window. In my case, the user name is
// always there from my windows credentials. So normally I would type in the
// password and press ENTER to login. But here I'll use SendKeys to mimic my
// behavior.
SendKeys.SendWait(password); // send password string
SendKeys.SendWait("{ENTER}"); // send ENTER key
// Now the client should be logging in for you! :)
// IMPORTANT NOTE
// If you are using a console application like I am, you must add a reference to
// System.Windows.Forms to your project and put "using System.Windows.Forms;" in
// your code. This is required to use the "SendKeys" function.
//
// Also this code is just for my testing (quick and dirty), you will want to write
// more checks and catch errors and such. You should probably give the
// WaitForInputIdle a timeout etc...
}
謝謝你的建議,我接過了另一個項目,但現在我又回到了這個項目。我明天就會拍攝這張照片,看看它能否與我所擁有的一樣。 – akagixxer