Pergunta

Resumindo a história, estou tentando automatizar algumas coisas quando meu computador inicializa.Pensei em escrever um aplicativo de console C# para fazer isso e depois adicioná-lo a uma tarefa agendada no Windows para ser executada na inicialização.Meu problema é com um programa, ele requer senha e não tem opções para abrir pela linha de comando.Portanto, deve ser inserido manualmente.Meu pensamento era recuperar minha senha de um banco de dados KeePass e usar SendKeys para inserir a senha e fazer login no programa.O problema que estou tendo é o tempo que leva para carregar;Não tenho como detectar quando a interface GUI foi carregada e está pronta para meus SendKeys.Existe alguma maneira de detectar isso?Presumo que tudo o que tenho para trabalhar é a classe "Process", já que foi ela que usei para executar o programa.Observe também que quando executo o executável usando Process.Start(), o programa cria outro processo para efetuar login, mas não possui nenhuma janela associada que eu possa ver usando chamadas de API do Windows.

Ok, isso foi longo, posso recapitular ...

Problema:Do C#, detectando quando um programa de terceiros foi carregado (ou seja,a tela inicial desapareceu e a GUI está pronta para a interação do usuário - o que significa que não posso confiar apenas se o processo está em execução ou não).Além disso, não há opções de linha de comando para o programa de terceiros, ou eu apenas o executaria com a senha como argumento.

Meta:Usar SendKeys para automatizar a inserção de uma senha, mas meu programa deve aguardar o carregamento do aplicativo de terceiros.

Notas:Usando o aplicativo de console C# .NET 3.5 NÃO detectando carga para o meu próprio formulário, mas um terceiro, caso contrário, isso seria fácil (ou seja,evento form_loaded...)

Obrigado por olhar minha pergunta, se quiser mais detalhes ou qualquer coisa me avise.

ATUALIZAR:

Problema resolvido!As duas respostas que recebi combinaram-se para me dar a solução que queria.Então, se alguém se deparar com isso mais tarde, aqui está o que fiz para que funcionasse.

Portanto, este programa automatiza o login para algum software cliente no qual você deve fazer login.Meu problema era que o software não oferecia opção ou documentação para parâmetros de linha de comando que muitos outros programas oferecem para que você possa fazer login com um arquivo-chave ou algo assim.Este programa também desabilitou copiar e colar para que a senha TEM que ser digitada manualmente, o que é uma grande dor se você usar senhas como eu, longas e complicadas, sem padrões.Então, escrevi este programa para meu benefício e também para outras pessoas no trabalho;Acabei de programá-lo para ser executado no logon em minha máquina Windows e ele abre o software cliente e executa o login automaticamente.

//
// 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...
}
Foi útil?

Solução

Você pode verificar com Process.WaitForInputIdle depois de iniciar um processo e esperar até que seja totalmente iniciado. Aqui está um exemplo simples:

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

Outras dicas

Tente olhar para isso: http://www.acoolsip.com/a-cool-blog/science-and-technology/151-c-sending-commands-to-independent-windows.html

você pode verificar se a janela é mostrada (através do link) e depois enviar mensagens (também no link)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top