Frage

Ich habe eine C#-Winforms-Anwendung, die von Zeit zu Zeit eine externe Exe-Datei starten muss, aber ich möchte keinen anderen Prozess starten, wenn bereits einer läuft, sondern lieber zu diesem wechseln.

Wie würde ich das also in C# im folgenden Beispiel umsetzen?

using System.Diagnostics;

...

Process foo = new Process();

foo.StartInfo.FileName = @"C:\bar\foo.exe";
foo.StartInfo.Arguments = "Username Password";

bool isRunning = //TODO: Check to see if process foo.exe is already running


if (isRunning)
{
   //TODO: Switch to foo.exe process
}
else
{
   foo.Start(); 
}
War es hilfreich?

Lösung

Das sollte es für Sie tun.

Prozesse prüfen

//Namespaces we need to use
using System.Diagnostics;

public bool IsProcessOpen(string name)
{
    //here we're going to get a list of all running processes on
    //the computer
    foreach (Process clsProcess in Process.GetProcesses()) {
        //now we're going to see if any of the running processes
        //match the currently running processes. Be sure to not
        //add the .exe to the name you provide, i.e: NOTEPAD,
        //not NOTEPAD.EXE or false is always returned even if
        //notepad is running.
        //Remember, if you have the process running more than once, 
        //say IE open 4 times the loop thr way it is now will close all 4,
        //if you want it to just close the first one it finds
        //then add a return; after the Kill
        if (clsProcess.ProcessName.Contains(name))
        {
            //if the process is found to be running then we
            //return a true
            return true;
        }
    }
    //otherwise we return a false
    return false;
}


Andere Tipps

Sie können auch LINQ verwenden,

var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));

Ich habe die AppActivate-Funktion in der VB-Laufzeit verwendet, um einen vorhandenen Prozess zu aktivieren.Sie müssen die Microsoft.VisualBasic-DLL in das C#-Projekt importieren.

using System;
using System.Diagnostics;
using Microsoft.VisualBasic;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] proc = Process.GetProcessesByName("notepad");
            Interaction.AppActivate(proc[0].MainWindowTitle);
        }
    }
}

Sie können Prozesse einfach mit aufzählen Process.GetProcesses Methode.

Ich habe herausgefunden, dass Mutex nicht wie in der Konsolenanwendung funktioniert.Die Verwendung von WMI zum Abfragen von Prozessen, die im Task-Manager-Fenster angezeigt werden können, wird Ihr Problem lösen.

Verwenden Sie so etwas:

static bool isStillRunning() {
   string processName = Process.GetCurrentProcess().MainModule.ModuleName;
   ManagementObjectSearcher mos = new ManagementObjectSearcher();
   mos.Query.QueryString = @"SELECT * FROM Win32_Process WHERE Name = '" + processName + @"'";
   if (mos.Get().Count > 1)
   {
        return true;
    }
    else
        return false;
}

NOTIZ:Fügen Sie den Assemblyverweis „System.Management“ hinzu, um den Typ Intellisense zu aktivieren.

Ich denke, die vollständige Antwort auf Ihr Problem erfordert ein Verständnis dafür, was passiert, wenn Ihre Anwendung feststellt, dass eine Instanz von foo.exe bereits ausgeführt wird, d. h. was „//TODO:“ bewirkt.„Zum foo.exe-Prozess wechseln“ eigentlich bedeuten?

In einem früheren Projekt musste ich die mehrfache Ausführung eines Prozesses verhindern, also habe ich im Init-Abschnitt dieses Prozesses Code hinzugefügt, der einen benannten Mutex erstellt.Dieser Muttext wurde erstellt und erworben, bevor der Rest des Prozesses fortgesetzt wurde.Wenn der Prozess den Mutex erstellen und abrufen kann, ist er der erste, der ausgeführt wird.Wenn der Mutex bereits von einem anderen Prozess gesteuert wird, ist derjenige, der fehlschlägt, nicht der erste, sodass er sofort beendet wird.

Ich habe lediglich versucht, die Ausführung einer zweiten Instanz aufgrund von Abhängigkeiten von bestimmten Hardwareschnittstellen zu verhindern.Je nachdem, was Sie mit dieser „Wechsel zu“-Zeile benötigen, benötigen Sie möglicherweise eine spezifischere Lösung, z. B. eine Prozess-ID oder ein Handle.

Außerdem hatte ich Zugriff auf den Quellcode des Prozesses, den ich starten wollte.Wenn Sie den Code nicht ändern können, ist das Hinzufügen des Mutex offensichtlich keine Option.

Zwei Bedenken, die Sie im Hinterkopf behalten sollten:

  1. Ihr Beispiel bestand darin, ein Passwort in eine Befehlszeile zu platzieren.Diese ClearText -Darstellung eines Geheimnisses könnte eine Sicherheitsanfälligkeit sein.

  2. Fragen Sie sich beim Aufzählen von Prozessen, welche Prozesse Sie wirklich aufzählen möchten.Alle Benutzer oder nur der aktuelle Benutzer?Was ist, wenn der aktuelle Benutzer zweimal angemeldet ist (zwei Desktops)?

Mnebuerquo schrieb:

Außerdem hatte ich Quellcodezugriff auf den Prozess, den ich starten wollte.Wenn Sie den Code nicht ändern können, ist das Hinzufügen des Mutex offensichtlich keine Option.

Ich habe keinen Quellcodezugriff auf den Prozess, den ich ausführen möchte.

Am Ende habe ich den Prozess MainWindowHandle verwendet, um zu dem Prozess zu wechseln, sobald ich festgestellt habe, dass er bereits ausgeführt wird:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top