C#SendKeys在发送前等待程序加载

时间:2012-05-22 21:03:26

标签: c# process executable sendkeys loaded

长话短说,我试图在电脑启动时自动完成一些事情。我以为我会编写一个C#控制台应用程序来执行此操作,然后将其添加到Windows中的计划任务中以便在启动时执行。我的问题是一个程序,它需要一个密码,没有选项可以通过命令行打开。因此必须手动输入。我的想法是从KeePass数据库中检索我的密码,并使用SendKeys输入密码并登录该程序。我遇到的问题是加载所需的时间;我无法检测GUI界面何时加载并准备好我的SendKeys。有没有办法检测到这个?我假设我必须使用的是“Process”类,因为那是我用来运行程序的。另请注意,当我使用Process.Start()运行可执行文件时,程序会创建另一个用于登录的进程,但它没有使用Windows API调用可以看到的关联窗口。

好的,我可以重新上限......

问题: 从C#检测第三方程序何时加载(即启动画面消失,GUI已准备好进行用户交互 - 这意味着我不能仅依赖于进程是否正在运行)。 此外,没有第三方程序的命令行选项,或者我只是以密码作为参数运行它。

目标: 要使用SendKeys自动输入密码,但我的程序必须等待第三方应用程序完成加载。

注意: 使用C#.NET 3.5控制台应用程序 不检测我自己的表单的负载,但是第三方不会检测负载(即form_loaded event ...)

感谢您查看我的问题,如果您想了解更多详情或任何事情让我知道。

更新

问题解决了! 我收到的两个答案结合起来给了我想要的解决方案。因此,如果有人在以后遇到这个问题,我就采取了以下措施来实现这一目标。

因此,此程序会自动登录您必须登录的某些客户端软件。我的问题是该软件没有为许多其他程序提供的命令行参数提供选项或文档,因此您可以使用密钥文件或其他东西登录。该程序还禁用了复制和粘贴,因此密码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...
}

2 个答案:

答案 0 :(得分:0)

尝试查看:http://www.acoolsip.com/a-cool-blog/science-and-technology/151-c-sending-commands-to-independent-windows.html

您可以检查窗口是否显示(使用链接)然后发送消息(也在链接上)

答案 1 :(得分:0)

您可以在启动进程后检查Process.WaitForInputIdle,并等到完全启动,这是一个简单的示例:

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