Envoyer un message à un processus de Windows (et pas de ses de la fenêtre principale)
J'ai une application sur un début détecte si il y a un processus avec le même nom existe déjà en cours d'exécution et, le cas échéant, active l'application en cours d'exécution de la fenêtre, puis se ferme.
Le problème est que la fenêtre principale peut être cachée (seulement une icône de zone de notification visible), donc me laissant sans la poignée de la fenêtre.
Au démarrage, l'instance précédente de MainWindowHandle
propriété est 0, donc je ne peux pas envoyer ShowWindow
ou PostMessage
.
Est il possible que je peux envoyer un message qui peut être intercepté par l'application en cours d'exécution, ce qui lui permet d'afficher sa fenêtre principale?
L'application est écrite en C#, le code que j'utilise pour réaliser ce ci-dessous.
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyMutexName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
Interop.WINDOWINFO pwi = new Interop.WINDOWINFO();
IntPtr handle = process.MainWindowHandle;
var isVisible = Interop.GetWindowInfo(handle, ref pwi);
if (!isVisible)
{
MessageBox.Show(Constants.APP_NAME + " is already running, check the notification area (near the clock).",
Constants.APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);//temporary message, until I find the solution
//Interop.ShowWindow(handle, Interop.WindowShowStyle.ShowNormal);
//Interop.PostMessage(handle, Interop.WM_CUSTOM_ACTIVATEAPP, IntPtr.Zero, IntPtr.Zero);
}
else
Interop.SetForegroundWindow(handle);//this works when the window is visible
break;
}
}
}
}
}
}
OriginalL'auteur chitza | 2009-11-22
Vous devez vous connecter pour publier un commentaire.
Voici comment j'ai fait:
J'espère que j'ai transcrit ce correctement. J'ai dû laisser de côté beaucoup d'autres choses, mais je crois que j'ai de ce qui est nécessaire. Ce que j'ai fonctionne pour moi sans échec. Si vous avez un problème, faites le moi savoir, et je vais voir ce que j'ai manqué.
Merci. Post est mis à jour en conséquence.
Beau travail, Mat ! fyi : construit, fonctionne très bien dans VS 2010 beta 2 compilé contre FrameWork 4.0. Ce que j'aime vraiment à propos de cette est que vous pouvez mettre un appel à " MessageBox.Afficher("..."); dans le cas où vous êtes de ré-activer le seul et unique exemple de laisser l'utilisateur de savoir ce qu'il se passe. Ma seule question serait autour de la question de la mise de l'activation dans un bloc try-catch de sorte que vous pouvez libérer le Mutex : est-ce que avoir des implications pour le comportement de l'application si le formulaire principal de l'instance continue de créer d'autres formes ou quoi ?
La seule indésirables implication, je pense, si un thread de premier plan est à gauche en cours d'exécution après la MainForm a quitté. Dans ce cas, l'application disparaît de la vue, mais reste en vie jusqu'à ce que le thread de premier plan de finitions. Cela pourrait être mauvais mojo si l'utilisateur a essayé de "relancer" l'application, car le même thread de premier plan pourrait être créé un deuxième temps. Dans mon cas, ce n'est pas un problème parce que je n'utilise que des threads d'arrière-plan, de sorte que l'application meurt immédiatement lorsque la MainForm sorties.
Il n'y a rien de techniquement mal avec remplacement du bloc try/catch avec l'aide d'instruction. L'instruction à l'aide veillera à ce que le Mutex est éliminé correctement même si une exception est levée. Mais c'est précisément pourquoi j'utilise le bloc try/catch. Si une exception non gérée se produit, mon instruction catch enregistre l'erreur dans l'observateur d'événements si je au moins avoir un aperçu de ce qui s'est passé. Alternativement, vous pouvez afficher les détails de l'exception dans une MessageBox. L'utilisation de déclaration n'a pas les moyens de vous la capacité de le faire.
OriginalL'auteur Matt Davis
Pour d'autres personnes qui veulent ce faire, je vais l'afficher en dessous de ma mise en œuvre, à l'aide de Matt Davis solution.
Dans Le Programme.cs
Dans MainForm.cs
Je ne pense pas que la forme réduite. Le code ne gère que les fenêtres masquées et non réduite arrière-plan de windows. Toutefois, le code doit être réécrit et de ne poster le message dans le Programme.cs, la fenêtre d'activation/de restauration code doit être dans WndProc (MainForm.cs). Je vais réécrire le week-end et le rediffuser.
OriginalL'auteur
Les Tubes nommés peut être utilisé pour cela. Il pourrait être plus acceptable .net.Vous pouvez définir un service dans l'application principale qui accepte un message à partir de l'application appelante. Voici un échantillon de ce service, en vb. Il demande l'application principale et passe une chaîne de caractères, dans ce cas, un nom de fichier. Il a également retourne une chaîne de caractères, mais tous les paramètres peuvent être utilisés ici.
Le programme d'installation de l'application appelante est un peu plus impliqué. L'appelant et de l'application principale peut être la même application.
J'ai cherché d'autres moyens de communication inter-processus et en effet, c'était l'une des alternatives, mais je crois à l'aide de simples Veuves des messages est plus doux et plus simple.
ouais, avec de radiodiffusion PostMessage, pas vraiment si la lumière, est-il?
OriginalL'auteur xpda