Start mehrerer Instanzen eines Programms verhindern
Ich hab nur aufwändige Programmierungen mit Windows-Titel-Abfrage usw. gesehen. Und meist testen dann die Anwendungen selbst und müssen sich erst wieder schließen.
Meine Lösung ist eine Batch. Wo die Execution-Policy es erlaubt, kann auch der Command in " " als .ps1 gespeichert werden. In dieser auf eine Zeile reduzierten Fassung und mit powershell -Command statt powershell -File läuft die Batch auch, wenn die Execution-Policy unklar oder Restricted ist.
Warum eine Batch, warum nicht die Zeile direkt in das Target-Feld eines .lnk-Files schreiben? Auch mit Kommandozeilen-Parameter-Abkürzung (-c statt -Command), Powershell-Aliasen (gps, ?, measure, start), Umgebungsvariablen und 8.3-Pfaden und -Namen ließ sich die Zeile nicht weit genug kürzen, dass sie mit dem langen Pfad und Namen "meiner" Anwendung in das Target-Feld einer .lnk passt. (Übrigens: .NET-Programme finden ihre .config nicht, wenn sie mit execu~1.exe aufgerufen werden, da muss man wenigstens den Namen ausschreiben.)
Diese Batch ist als Target eines .lnk gedacht. Andere .lnk kann man löschen. Direktes mehrfaches Starten einer .exe fängt es nicht ab. Das war auch nicht meine Anforderung.
Meine Lösung ist eine Batch. Wo die Execution-Policy es erlaubt, kann auch der Command in " " als .ps1 gespeichert werden. In dieser auf eine Zeile reduzierten Fassung und mit powershell -Command statt powershell -File läuft die Batch auch, wenn die Execution-Policy unklar oder Restricted ist.
%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -Command "&{ if ( (Get-Process | Where-Object {$_.ProcessName -eq 'calc'} | Measure-Object).Count -eq 0 ) { Start-Process 'calc' } else { add-type -AssemblyName microsoft.VisualBasic ; [Microsoft.VisualBasic.Interaction]::AppActivate('calc') } }"
Diese Batch ist als Target eines .lnk gedacht. Andere .lnk kann man löschen. Direktes mehrfaches Starten einer .exe fängt es nicht ab. Das war auch nicht meine Anforderung.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 247816
Url: https://administrator.de/contentid/247816
Ausgedruckt am: 25.11.2024 um 22:11 Uhr
13 Kommentare
Neuester Kommentar
Moin,
warum machst Du nicht einfach ein lockfile:
Standardverfahren seit Jahrzehnten (mindestens seit fast einem halben Jahrhundert).
Und wenn das Programm/das batchfile mal abstürzt, ohne das Lockfile zu löschen, kann man es manuell löschen.
lks
PS: man kanmn das ganz natürlich noch ausgefeilter machen und in das lockfile die prozess-identifikation des Programms schreiben, so das das Lockfile nur dann als gültig erkannt wird, wenn der dazugehörige prozess noch läuft.
warum machst Du nicht einfach ein lockfile:
- beim Start wird geprüft, ob ein Lockfile (kann irgendwo, aber an einem fest definierten Ort sein) existiert.
- Wenn das lockfile existiert, darf das programm nicht starten.
- wenn es nicht existiert, legt die batchdatei ein lockfile an udn startet das Programm udn wartet dann, bis es beendet wird.
- Wenn das programm beendet wird, löscht die batchdatei das lockfile.
Standardverfahren seit Jahrzehnten (mindestens seit fast einem halben Jahrhundert).
Und wenn das Programm/das batchfile mal abstürzt, ohne das Lockfile zu löschen, kann man es manuell löschen.
lks
PS: man kanmn das ganz natürlich noch ausgefeilter machen und in das lockfile die prozess-identifikation des Programms schreiben, so das das Lockfile nur dann als gültig erkannt wird, wenn der dazugehörige prozess noch läuft.
Moin,
also ich habe das bei mir wirklich sehr simple gelöst...
Einfach in der Aufgabenplanung den Task erstellt und gesagt, dass er nur einmal aufgerufen werden darf. der Rest ist dann ein Aufruf des Tasks. Ob direkt per Link oder mit Batch ist dann egal.
Allerdings ist deine Lösung auch nicht gerade unelegant.
Gruß
Chris
also ich habe das bei mir wirklich sehr simple gelöst...
Einfach in der Aufgabenplanung den Task erstellt und gesagt, dass er nur einmal aufgerufen werden darf. der Rest ist dann ein Aufruf des Tasks. Ob direkt per Link oder mit Batch ist dann egal.
Allerdings ist deine Lösung auch nicht gerade unelegant.
Gruß
Chris
also was wirklcih sicher ist:
man holt sich die Liste der laufenden Prozesse ab
entdeckt die Applikation dabei daß eine .exe mit demselben Namen schon in der Liste auftaucht dann startet sie nicht.
LCK Dateien haben halt den Nachteil daß sie liegenbleiben wenn die Applikation aus irgendeinem Grunde abstürzen sollte.
Im Dot net Framework ist die Prozeßliste hier untergebracht:
system.diagnostics.process.GetProcesses
man holt sich die Liste der laufenden Prozesse ab
entdeckt die Applikation dabei daß eine .exe mit demselben Namen schon in der Liste auftaucht dann startet sie nicht.
LCK Dateien haben halt den Nachteil daß sie liegenbleiben wenn die Applikation aus irgendeinem Grunde abstürzen sollte.
Im Dot net Framework ist die Prozeßliste hier untergebracht:
system.diagnostics.process.GetProcesses
@70866
Genau das passiert doch in dem Einzeiler.
Der Weg dahin ist nur etwas kompliziert. Eine Batchdatei, die die PowerShell aufruft, die dann ggf. eine VB Methode aufruft.
Übrigens funktioniert das Beispiel bei mir nicht. AppActivate möchte gern den Fenstertitel übergeben bekommen, und der ist (auf meinem deutschen Win7 x86) nicht, auch nicht teilweise, "calc" sondern "Rechner".
Der Anspruch, es anders zu machen als ...
AppActivate aktiviert ein minimiertes Programm übrigens nur in der Taskleiste und holt nicht das Fenster zurück auf den Bildschirm. (Anders bei Fenstern im Hintergrund. Diese werden in den Vordergrund gebracht und erhalten den Fokus.)
Grüße
rubberman
Genau das passiert doch in dem Einzeiler.
Der Weg dahin ist nur etwas kompliziert. Eine Batchdatei, die die PowerShell aufruft, die dann ggf. eine VB Methode aufruft.
Übrigens funktioniert das Beispiel bei mir nicht. AppActivate möchte gern den Fenstertitel übergeben bekommen, und der ist (auf meinem deutschen Win7 x86) nicht, auch nicht teilweise, "calc" sondern "Rechner".
Der Anspruch, es anders zu machen als ...
Ich hab nur aufwändige Programmierungen mit Windows-Titel-Abfrage usw. gesehen.
... wird so leider teilweise ad absurdum geführt.AppActivate aktiviert ein minimiertes Programm übrigens nur in der Taskleiste und holt nicht das Fenster zurück auf den Bildschirm. (Anders bei Fenstern im Hintergrund. Diese werden in den Vordergrund gebracht und erhalten den Fokus.)
Grüße
rubberman
Hallo mupan7.
Grüße
rubberman
Vielleicht gibt es als Nachbarn auch eine AppMaximize-Methode, die implizit das Fenster fokussiert?
Nein, gibt es nicht. Und ein Cmdlet gibt es imho tatsächlich auch nicht. Einzige Möglichkeit ist soweit ich weiß die Verwendung der WinAPI ShowWindow()
oder ShowWindowAsync()
aus der user32.dll. Damit ließe sich sicher ein benutzerdefiniertes Cmdlet erstellen, einfacher wird es damit aber wiederum nicht und kommt vermutlich für dich auch nicht infrage...Grüße
rubberman