it-swarm-pt.tech

.NET (C #): Obtendo janelas filho quando você só tem um identificador de processo ou PID?

Tipo de problema de caso especial:

  • Eu inicio um processo com System.Diagnostics.Process.Start(..)
  • O processo abre uma tela inicial - essa tela se torna a janela principal.
  • A tela inicial fecha e a IU 'real' é exibida. A janela principal (tela inicial) agora é inválida.
  • Eu ainda tenho o objeto Process e posso consultar seu identificador, módulo, etc. Mas o identificador da janela principal agora é inválido.

Preciso obter a IU do processo (ou identificador da IU) neste ponto. Suponha que não posso mudar o comportamento do processo para tornar isso mais fácil (ou mais são).

Procurei online, mas admito que não procurei por mais de uma hora. Parecia que deveria ser um tanto trivial :-(

22
shea241

Se você não se importa em usar a API do Windows, pode usar EnumWindowsProc e verificar cada uma das alças que aparecem usando GetWindowThreadProcessId (para ver se está em seu processo), e então talvez IsWindowVisible, GetWindowCaption e GetWindowTextLength para determinar qual hWnd em seu processo é o único você quer.

Porém, se você não usou essas funções antes, essa abordagem será uma dor real, então, esperançosamente, existe uma maneira mais simples.

11
MB.

@ageektrapped está no caminho certo, entretanto FindWindow não pesquisará janelas-filhas.

Para isso, você precisará usar FindWindowEx

7
Ash

Obrigado por suas respostas. Graças a você aqui, descobri como saber se a janela principal de um processo está na frente ou não:

N.B: é claro que isso precisa de System.Diagnostic e System.Runtime.Interrop

public bool IsWindowActive(Int32 PID)
{
  return IsWindowActive(Process.GetProcessById(PID));
}

[DllImport("user32.dll")]
private static extern
IntPtr GetForegroundWindow();

public bool IsWindowActive(Process proc)
{
  proc.Refresh();
  return proc.MainWindowHandle.Equals(GetForegroundWindow());
}
3
Giova

Você pode descobrir que, se chamar .Refresh (), obterá a nova janela de nível superior.

2
GregUzelac

Use Process.GetProcessById (proc.Id); onde proc era sua tela inicial. Funciona para mim.

Agora, como você obtém as propriedades da janela principal em System.Windows.Forms para focalizá-la sem usar win32? Afinal, o .net deve ser uma solução completa - não é?

1
Michael Lastufka

Se você souber o título da janela, poderá usar a chamada Win32, FindWindow, por meio de P/Invoke.

Você pode encontrar a assinatura aqui em pinvoke.net

1
ageektrapped

Pelo que entendi, a propriedade MainWindowHandle do processo que você está iniciando não é válida. Se for esse o caso, você pode usar a função FindWindow (do Win32 SDK) que retorna o identificador de janela de que você precisa. Tudo que você precisa é o nome da classe da janela principal do aplicativo de destino. Você pode obtê-lo usando Spy ++ ou Winspector . Você também precisa se certificar de que tem a janela certa, verificando a id do processo da janela usando GetWindowThreadProcessId .

Por fim, devo dizer que não sou um especialista em Win32 e talvez haja uma solução melhor para o seu caso.

1
blackwing

A propriedade MainWindowHandle é armazenada em cache depois de ser acessada pela primeira vez, por isso você não a vê mudando, mesmo depois que o identificador se torna inválido. As informações de GregUzelac estão corretas. Chamar Proces.Refresh fará com que a próxima chamada para Process.MainWindowHandle refaça a lógica para encontrar um novo identificador da janela principal. A lógica de Michael também funciona porque o novo Processo não tem uma versão em cache do MainWindowHandle.

0
Matt Ellis

Em algum lugar do código, a janela principal "real" é criada. Você pode apenas salvar o identificador da janela naquele momento e, em seguida, após o fechamento da tela inicial, você pode definir Application.MainWindow para a janela real.

0
Marcus Erickson