Клавиши отправки C # Ожидают загрузки программы перед отправкой

StackOverflow https://stackoverflow.com//questions/10710141

Вопрос

Короче говоря, я пытаюсь автоматизировать некоторые вещи при загрузке моего компьютера.Я подумал, что напишу консольное приложение на C # для этого, а затем добавлю его в задачу расписания в Windows, которая будет выполняться при загрузке.Моя проблема связана с одной программой, для нее требуется пароль, и у нее нет опций для открытия через командную строку.Таким образом, он должен быть введен вручную.Моя мысль состояла в том, чтобы получить свой пароль из базы данных KeePass и использовать SendKeys для ввода пароля и входа в программу.Проблема, с которой я столкнулся, заключается во времени, которое требуется для загрузки;У меня нет способа определить, когда графический интерфейс загружен и готов к моим ключам отправки.Есть ли какой-нибудь способ обнаружить это?Я предполагаю, что все, с чем мне нужно работать, - это класс "Process", поскольку именно его я использовал для запуска программы.Также обратите внимание, что когда я запускаю исполняемый файл с помощью Process .Start(), программа создает другой процесс для входа в систему, но у него нет связанного окна, которое я могу видеть с помощью вызовов Windows API.

Ладно, это было долго, я могу переписать...

Проблема:Из C #, определяющего, когда загрузилась сторонняя программа (т.е.заставка исчезла, и графический интерфейс готов к взаимодействию с пользователем - это означает, что я не могу просто полагаться на то, запущен Процесс или нет).Кроме того, нет параметров командной строки для сторонней программы, иначе я бы просто запустил ее с паролем в качестве аргумента.

Цель:Использовать SendKeys для автоматизации ввода пароля, но моя программа должна дождаться завершения загрузки стороннего приложения.

Примечания:Использование консольного приложения C # .NET 3.5 Обнаружение загрузки не для моей собственной формы, а для третьей стороны, иначе это было бы легко (т.Е.form_loaded событие...)

Спасибо, что рассмотрели мой вопрос, если вам нужны какие-либо дополнительные подробности или еще что-нибудь, дайте мне знать.

Обновить:

Проблема решена! Два ответа, которые я получил, объединились, чтобы дать мне решение, которое я хотел.Так что, если кто-нибудь столкнется с этим позже, вот что я сделал, чтобы это сработало.

Итак, эта программа автоматизирует вход в систему для некоторого клиентского программного обеспечения, в которое вы должны войти.Моя проблема заключалась в том, что программное обеспечение не предлагало опции или документации для праметров командной строки, которые предлагают многие другие программы, чтобы вы могли войти в систему с помощью ключевого файла или чего-то еще.Эта программа также отключила копирование и вставку, поэтому пароль ПРИХОДИТСЯ вводить вручную, что является большой проблемой, если вы используете пароли, как я, длинные сложные пароли без шаблонов.Итак, я написал эту программу для себя, а также для других сотрудников;Я просто планирую запустить его при входе на мой компьютер с 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...
}
Это было полезно?

Решение

Вы можете проверить с помощью Process .WaitForInputIdle после запуска процесса и дождитесь его полного запуска, вот простой пример :

http://msdn.microsoft.com/en-us/library/xb73d10t%28v=vs.71%29.aspx

Другие советы

Попробуй взглянуть на это: http://www.acoolsip.com/a-cool-blog/science-and-technology/151-c-sending-commands-to-independent-windows.html

вы можете проверить, отображается ли окно (используя ссылку), а затем отправлять сообщения (также по ссылке).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top