Pergunta

Aqui está o meu problema: eu preciso para fechar um processo, já em execução, a partir de um programa C #. O problema é que o processo funciona agora como um ícone (minimizado barra de tarefas), ea menos que o usuário abri-lo pelo menos uma vez (que nunca vai acontecer em máquinas automáticas), que nunca vai tem uma janela principal.

O outro requisito que eu tenho é que a aplicação seja fechado não matou . Eu preciso dele para escrevê-lo de buffers de memória para o disco - e matá-lo causa perda de dados

.

Aqui está o que eu tentei até agora:

        foreach (Process proc in Process.GetProcesses())
        {
            if (proc.ProcessName.ToLower().StartsWith("myapp"))
            {
                if (proc.MainWindowHandle.ToInt32() != 0)
                {
                    proc.CloseMainWindow();
                    proc.Close();
                    //proc.Kill();  <--- not good!
                }
            }
        }

Eu adicionei o se cláusula, depois de descobrir que MainWindowHandle == 0 quando a janela foi minimizada. Remover o se não ajuda. Nem o CloseMainWindow () , nem o Close () trabalho. O Kill () faz, mas como mencionado acima -. Não é o que eu preciso

Qualquer ideia seria aceito, incluindo o uso de arcanos funções da API Win32:)

Foi útil?

Solução 3

Aqui estão algumas respostas e esclarecimentos:

rpetrich : Tentou o seu método antes eo problema é, eu não sei o nome da janela, ele difere de usuário para usuário, versão para versão - apenas o nome exe permanece constante. Tudo o que tenho é o nome do processo. E como você pode ver no código acima da MainWindowHandle do processo é 0.

Roger : Sim, eu queria dizer a área de notificação da barra de tarefas - Obrigado pelo esclarecimento. I NECESSIDADE para chamar PostQuitMessage. Eu só não sei como, dada apenas uma processs, e não uma janela.

Craig : Eu ficaria feliz em explicar a situação: o aplicativo tem uma interface de linha de comando, o que lhe permite especificar os parâmetros que ditam o que ele iria fazer e onde ele vai salvar os resultados. Mas uma vez que está em execução, a única maneira de pará-lo e obter os resultados é botão direito do mouse na notificação bandeja está e selecione 'saída'.

Agora meus usuários querem script / batch o aplicativo. Eles tinham absolutamente nenhum problema de iniciá-lo a partir de um lote (basta especificar o nome exe e e um monte de bandeiras), mas, em seguida, ficou preso com um processo em execução. Supondo que ninguém vai mudar o processo para fornecer uma API para pará-lo durante a execução (que é bastante antigo), eu preciso de uma maneira de artificialmente fechá-lo.

Da mesma forma, em computadores sem supervisão, o script para iniciar o processo pode ser iniciado por um programa de controle de agendamento de tarefas ou operações, mas não há nenhuma maneira de fechar o processo.

Hope que esclarece a minha situação e, novamente, agradece a todos que está tentando ajudar!

Outras dicas

Isso deve funcionar:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

private const int WM_CLOSE = 0x10;
private const int WM_QUIT = 0x12;

public void SearchAndDestroy(string windowName) 
{
    IntPtr hWnd = FindWindow(null, windowName);
    if (hWnd == IntPtr.Zero)
        throw new Exception("Couldn't find window!");
    SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}

Uma vez que algumas janelas não respondem a WM_CLOSE, WM_QUIT pode ter que ser enviado em seu lugar. Estas declarações devem trabalhar em ambos 32 bits e 64 bits.

Se é na barra de tarefas, ele vai ter uma janela. Ou você quis dizer que é na área de notificação da barra de tarefas (também conhecido como o SysTray)? Nesse caso, ele ainda vai ter uma janela.

aplicações Win32 não tem realmente uma "janela principal", a não ser por convenção (a janela principal é a que chama PostQuitMessage em resposta a WM_DESTROY, fazendo com que o ciclo de mensagem para sair).

Com o programa em execução, executar Spy ++. Para encontrar todas as janelas pertencentes a um processo, você deve selecionar Spy -> Processos no menu principal. Isto irá exibir uma árvore de processos. De lá, você pode navegar para tópicos, e depois para janelas. Isso vai lhe dizer que o Windows o processo tem. Anote a classe de janela e legenda. Com estes, você pode usar FindWindow (ou EnumWindows) para encontrar o identificador de janela no futuro.

Com o identificador de janela, você pode enviar uma WM_CLOSE ou WM_SYSCOMMAND / SC_CLOSE (equivalente a clicar no 'X' na legenda da janela) mensagem. Isso deve fazer com que o programa para encerrar bem.

Note que eu estou falando de um Win32 ponto de vista aqui. Você pode precisar usar P / Invoke ou outros truques para chegar a este trabalho a partir de um programa de .NET.

Pergunta para esclarecer por que você está tentando isso: Se a única interface de usuário no processo é o ícone da bandeja do sistema, por que você iria querer matar isso e, mas deixar o processo em execução? Como é que o usuário acessar o processo? E se a máquina é "autônoma", porque preocupação-se com o ícone da bandeja?

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