Question

Voici mon problème: je dois fermer un processus déjà en cours à partir d'un programme C #. Le problème est que le processus s’exécute maintenant sous forme d’icône (réduite à la barre des tâches) et que, si l’utilisateur ne l’ouvre pas au moins une fois (ce qui ne se produira jamais sur des ordinateurs sans surveillance), il ne se produira jamais. avoir une fenêtre principale.

Mon autre exigence est que l'application soit fermée , pas mise à mort . J'en ai besoin pour écrire ses mémoires tampons sur le disque - et les tuer entraîne la perte de données.

Voici ce que j'ai essayé jusqu'à présent:

        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!
                }
            }
        }

J'ai ajouté la clause if après avoir découvert que MainWindowHandle == 0 lorsque la fenêtre avait été réduite. Supprimer si ne vous aide pas. Ni le CloseMainWindow () , ni le Close () travail. Kill () le fait, mais comme mentionné ci-dessus, ce n'est pas ce dont j'ai besoin.

Toute idée serait acceptée, y compris l'utilisation des fonctions complexes de l'API Win32:)

Était-ce utile?

La solution 3

Voici quelques réponses et clarifications:

rpetrich : J’ai essayé votre méthode auparavant et le problème est que je ne connais pas le nom de la fenêtre, elle diffère d’un utilisateur à l’autre, d’une version à l’autre - seul le nom exe reste constant. Tout ce que j'ai, c'est le nom du processus. Et comme vous pouvez le constater dans le code ci-dessus, le paramètre MainWindowHandle du processus est égal à 0.

Roger : Oui, je voulais dire la zone de notification de la barre des tâches - merci pour la clarification. Je BESOIN d'appeler PostQuitMessage. Je ne sais tout simplement pas comment, étant donné les processus uniquement et non une fenêtre.

Craig : Je serais heureux d'expliquer la situation: l'application dispose d'une interface de ligne de commande, vous permettant de spécifier des paramètres qui déterminent ce qu'elle ferait et où elle enregistrera les résultats. Mais une fois qu’il est en cours d’exécution, le seul moyen de l’arrêter et d’obtenir les résultats consiste à cliquer avec le bouton droit de la souris sur la notification de notification et à sélectionner «Quitter».

Maintenant, mes utilisateurs veulent créer un script / un lot dans l'application Ils n’avaient absolument aucun problème à le démarrer à partir d’un lot (il suffit de spécifier le nom du fichier exe et un groupe de drapeaux) mais se sont retrouvés coincés dans un processus en cours. En supposant que personne ne changera le processus afin de fournir une API pour l'arrêter en cours d'exécution (il est assez ancien), j'ai besoin d'un moyen de le fermer artificiellement.

De même, sur les ordinateurs non surveillés, le script de démarrage du processus peut être lancé par un programme de contrôle des opérations ou de planification des tâches, mais il n’ya aucun moyen de mettre fin au processus.

J'espère que cela clarifie ma situation et, encore une fois, merci à tous ceux qui essaient d'aider!

Autres conseils

Cela devrait fonctionner:

[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);
}

Certaines fenêtres ne répondant pas à WM_CLOSE , il peut être nécessaire d'envoyer WM_QUIT à la place. Ces déclarations devraient fonctionner à la fois en 32 bits et en 64 bits.

Si cela se trouve dans la barre des tâches, il y aura une fenêtre. Ou voulez-vous dire que cela se trouve dans la zone de notification de la barre des tâches (alias SysTray)? Dans ce cas, il y aura toujours une fenêtre.

Les applications Win32 n'ont pas vraiment de "fenêtre principale", sauf convention contraire (la fenêtre principale est celle qui appelle PostQuitMessage en réponse à WM_DESTROY, entraînant la fermeture de la boucle de message).

Avec le programme en cours d'exécution, exécutez Spy ++. Pour rechercher toutes les fenêtres appartenant à un processus, vous devez sélectionner Spy - > Processus du menu principal. Cela affichera une arborescence de processus. À partir de là, vous pouvez accéder aux threads, puis aux fenêtres. Cela vous indiquera les fenêtres du processus. Notez la classe et la légende de la fenêtre. Avec ceux-ci, vous pouvez utiliser FindWindow (ou EnumWindows) pour rechercher le handle de fenêtre à l'avenir.

Avec le handle de fenêtre, vous pouvez envoyer un message WM_CLOSE ou WM_SYSCOMMAND / SC_CLOSE (équivalent à cliquer sur le "X" dans la légende de la fenêtre). Cela devrait entraîner une bonne fermeture du programme.

Notez que je parle d'un point de vue Win32 ici. Vous devrez peut-être utiliser P / Invoke ou d’autres astuces pour que cela fonctionne à partir d’un programme .NET.

Question pour préciser pourquoi vous tentez ceci: Si la seule interface utilisateur du processus est l'icône de la barre d'état système, pourquoi voudriez-vous le supprimer et laisser le processus en cours d'exécution? Comment l'utilisateur accèderait-il au processus? Et si la machine est "sans surveillance", pourquoi vous préoccuper de l'icône de la barre d'état?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top