C#SendKeys在发送前等待程序加载
-
13-12-2019 - |
题
这么长的故事短暂,我试图在我的电脑靴子上自动化一些东西。我以为我会编写一个C#控制台应用程序来执行此操作,然后将其添加到要在Boothup上执行的Windows中的计划任务。我的问题是一个程序,它需要一个密码,并且没有通过命令行打开选项。因此必须手动输入。我的思想是从KeePass数据库中检索我的密码,并使用SendKeys输入密码并登录程序。我拥有的问题是加载所需的时间;我无法检测到GUI接口加载并为我的Sendkeys准备好的方法。有没有办法来检测这个?我假设我必须使用的是“进程”类,因为这就是我曾经运行该程序的内容。另请注意,当我使用process.start()运行可执行文件时,程序会创建一个登录的另一个进程,但它没有任何相关窗口,我可以使用Windows API调用来查看。
好的,这是长的,我可以重新上限...
问题: 从C#检测到第三方程序加载时(即,飞溅屏幕消失了,GUI准备好用于用户交互 - 这意味着我不能依赖于进程是否正在运行)。 此外,第三方程序没有命令行选项,或者我只需用密码作为参数运行它。
目标: 要使用SendKeys才能自动输入密码,但我的程序必须等待第三方应用程序完成加载。
注意: 使用C#.NET 3.5控制台应用程序 没有为我自己的形式检测负载,而是第三方,否则这将是简单的(即form_loaded事件......)
谢谢你看看我的问题,如果你想要更多细节或任何东西让我知道。
更新:
问题解决了! 我收到的两个答案组合给我我想要的解决方案。所以,如果稍后有人来,这里就是我做的工作所做的。
所以这个程序为您必须登录的某些客户端软件自动启动登录。我的问题是该软件提供了不可选项或文件的命令行Prameters,其中许多其他程序提供,这样您就可以使用密钥文件或其他东西登录。此程序还禁用了副本和粘贴,因此密码必须手动键入,如果您使用像我这样的密码,那么长期复杂的无模式,这是一个很大的痛苦。所以我为我的福利写了这个程序,也为工作中的其他人写了;我只是安排它以登录到我的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
其他提示
您可以检查窗口是否显示(使用链接),然后发送消息(也在链接上)