Pergunta

Não sei quase nada sobre linq.

Eu estou fazendo isto:

var apps = from app in Process.GetProcesses()
    where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
    select app;

O que me dá todos os processos em execução que atendem a esses critérios.

Mas não sei como conseguir o primeiro.Os exemplos que posso encontrar na rede parecem implicar que tenho que fazer isso

var matchedApp = (from app in Process.GetProcesses()
    where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
    select app).First();

o que me parece um tanto feio e também lança uma exceção se não houver processos correspondentes.Existe uma maneira melhor?

ATUALIZAR

Na verdade, estou tentando encontrar o primeiro item correspondente e ligo SetForegroundWindow nele

Eu descobri essa solução, que também me parece feia e horrível, mas melhor que a anterior.Alguma ideia?

var unused = from app in Process.GetProcesses()
    where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
    select SetForegroundWindow( app.MainWindowHandle ); // side-effects in linq-query is technically bad I guess
Foi útil?

Solução

@FryHard FirstOrDefault funcionará, mas lembre-se de que retornará nulo se nenhum for encontrado.Este código não foi testado, mas deve estar próximo do que você deseja:

var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);

if (app == null)
    return;

SetForegroundWindow(app.MainWindowHandle);

Outras dicas

Fazer não usar Count() como diz o ICR. Count() irá iterar através do IEnumerable para descobrir quantos itens ele possui.Nesse caso, a penalidade de desempenho pode ser insignificante, pois não há muitos processos, mas é um mau hábito adquirir.Use apenas Count() quando sua consulta está interessada apenas no número de resultados. Count quase nunca é uma boa ideia.

Existem vários problemas com a resposta de FryHard.Primeiro, por causa execução atrasada, você acabará executando a consulta LINQ duas vezes, uma vez para obter o número de resultados e outra para obter o FirstOrDefault.Em segundo lugar, não há razão alguma para usar FirstOrDefault depois de verificar a contagem.Como ele pode retornar nulo, você nunca deve usá-lo sem verificar se há nulo.Ou faça apps.First().MainWindowHandle ou:

var app = apps.FirstOrDefault();

if (app != null)
    SetForegroundWindow(app.MainWindowHandle);

É por isso que a melhor solução é a de Mark, sem dúvida.É a maneira mais eficiente e estável de usar o LINQ para conseguir o que deseja.

Supondo que em seu primeiro exemplo, apps seja um IEnumerable, você pode usar as propriedades .Count e .FirstOrDefault para obter o único item que deseja passar para SetForegroundWindow.

var apps = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app;

if (apps.Count > 0)
{
    SetForegroundWindow(apps.FirstOrDefault().MainWindowHandle );
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top