Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

Start mehrerer Instanzen eines Programms verhindern

Tipp Entwicklung Batch & Shell

Mitglied: mupan7

mupan7 (Level 1) - Jetzt verbinden

30.08.2014, aktualisiert 31.08.2014, 3277 Aufrufe, 13 Kommentare

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.
01.
%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') } }"
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.
Mitglied: Lochkartenstanzer
30.08.2014 um 11:54 Uhr
Moin,

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.
Bitte warten ..
Mitglied: mupan7
30.08.2014, aktualisiert 03.09.2014
Hallo Lochkartenstanzer,

meine Lösung deckt meine Anforderung am besten ab. Ein Standardverfahren, das an der konkreten Anforderung vorbeigeht, bleibt gut, aber eben nicht hier.

Als Grund für die lockfile-Lösung kann ich mir z.B. vorstellen, wenn jede Startvariante des Programms abgefangen werden soll. Das brauche ich hier nicht.

Access arbeitet mit lockfiles (.ldb und aktuell glaube .laccdb?). Dieses Standardverfahren ist ein Standard-Supportfall, wenn du Access-Anwendungen betreuen musst
Bitte warten ..
Mitglied: Sheogorath
31.08.2014 um 05:18 Uhr
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
Bitte warten ..
Mitglied: 70866
31.08.2014 um 14:47 Uhr
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
Bitte warten ..
Mitglied: rubberman
31.08.2014, aktualisiert um 15:39 Uhr
@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 ...
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
Bitte warten ..
Mitglied: Endoro
31.08.2014, aktualisiert um 16:05 Uhr
Hey,
warum nicht eine Batch mit tasklist?
01.
tasklist |findstr "\<calc.exe\>" >nul && echo Läuft schon.|| calc.exe
Gruss Endoro
Bitte warten ..
Mitglied: An-dir
31.08.2014, aktualisiert um 16:55 Uhr
Hallo,
so hätte ich das auch gemacht Endoro

Kleiner Hinweis für mupan7:
Verwende find mit dem Parameter "/i" damit die Prozessprüfung nicht casesensitive ist oder beachte einfach die Schreibweise.

Gruß
Andi
Bitte warten ..
Mitglied: mupan7
03.09.2014, aktualisiert um 09:41 Uhr
@Endoro:

Danke. Für mich würde das völlig reichen. Ob es sicher ist, kommt auf den Einzelfall an, bekanntlich pipet cmd Strings, PowerShell dagegen Objekte, was tendenziell sicherer ist, aber bei eindeutigen Strings keinen Unterschied machen sollte.

Wesentlicher ist:

  • In einem PowerShell-Skript kann ich ohne Verrenkungen (nämlich ohne die Abhängigkeit von nicht zu den Bordmitteln gehörenden.exe's) Dialoge ausgeben. Welcher Enduser beim Kunden akzeptiert schon Befehlszeilenausgaben?

  • Die Ausgabe ist per Batch nur sehr schwer zu regionalisieren, also, in der Sprache des Anwenders oder ersatzweise Englisch zu halten, wo die Übersetzung nicht vorliegt.
Bitte warten ..
Mitglied: mupan7
03.09.2014 um 09:55 Uhr
@rubberman

Für meine Anforderung reicht der Versuch, die App zu aktivieren, wenn das nicht geht, dann halt nicht. Vielleicht gibt es als Nachbarn auch eine AppMaximize-Methode, die implizit das Fenster fokussiert? Ich hätte auch ohne den ganzen else-Block leben können, wichtig ist bei uns hier, dass die Anwendung nur einmal gestartet wird.

Dass der Admin testet und anpasst, bevor er so etwas auf sein User-Volk loslässt, davon geh ich aus.

Dass so eine Funktion auf jedem System andere Parameter-Werte verlangt, ist mal wieder typisch. Vielleicht lässt sich der Wert irgendwie ermitteln, mit sowas wie

FOR /F "usebackq tokens=2* delims==" %%g IN (`wmic group where sid^="S-1-5-32-544" get name /Value^`) do set admgrpname=%%g

(legt den lokalen, regionalisierten Namen der Administratoren-Usergroup in die Umgebungsvariable admgrpname), aber das macht es dann noch komplizierter und anfälliger. Also eher gar nichts, wenn es schon läuft.

Die Kompliziertheit kommt daher, dass ich der Batch-Pipe nicht traue, PowerShell-Zeilen aber nicht per Doppelklick ausführbar sind, PowerShell-Skripte von der ExecutionPolicy sehr wahrscheinlich abgefangen werden, ich nicht skrupellos genug bin, mir die Erlaubnis einfach per powershell -ExecutionPolicy zu holen, und dass es in v4 m.W. für das Aktivieren / Fokussieren eines Fenster kein Cmdlet gibt, ich außerdem beim Kunden von v2 ausgehen muss.
Bitte warten ..
Mitglied: mupan7
03.09.2014 um 10:08 Uhr
Moin Chris,

das behalte ich auf jeden Fall im Hinterkopf. Beim Deployen auf Clients beim Kunden, die ich nicht selbst administriere, müsste ich doch ein wenig Sorgfalt auf die Einstellungen zum User verwenden, und ein paar Testreihen in VMs hier starten. Es muss halt immer alles vorzugsweise auf Doppelklick laufen, oder von einem automatischen Setup eingerichtet werden.

Grüßle,

mupan
Bitte warten ..
Mitglied: mupan7
03.09.2014 um 10:10 Uhr
Stimmt, unbekannter Mod, das passt besser in Tipps.
Bitte warten ..
Mitglied: rubberman
03.09.2014 um 23:59 Uhr
Hallo mupan7.

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
Bitte warten ..
Mitglied: mupan7
04.09.2014, aktualisiert um 08:58 Uhr
Hi rubberman,

ich stelle mir grade vor, wie ich mein benutzerdefiniertes Cmdlet genervten Admins erkläre Nö, einfach muss es sein.

Im Fall des Falles könnte ich nircmd (nirsoft.net) mit ausrollen, dann heißt der Aufruf so:

"<Pfad>\nircmd.exe" win activate process calc.exe
Man muss ja nicht immer das Rad neu erfinden, und Aufwand und Nutzen müssen zur Anforderung passen.

Danke für's Zusammendenken, hat Spaß gemacht.
Bitte warten ..
Neuester Wissensbeitrag
Windows 10

Powershell 5 BSOD

(8)

Tipp von agowa338 zum Thema Windows 10 ...

Ähnliche Inhalte
Windows Update
Treiberinstallation durch Windows Update läßt sich nicht verhindern (17)

Frage von liquidbase zum Thema Windows Update ...

Batch & Shell
Batch zum bearbeiten mehrerer CSV (3)

Frage von Matzus87 zum Thema Batch & Shell ...

Windows 10
Nach Start kein Netzwerk (11)

Frage von MegaGiga zum Thema Windows 10 ...

E-Mail
Mailinglisten mehrerer Domains

Frage von tobilektri zum Thema E-Mail ...

Heiß diskutierte Inhalte
Microsoft
Ordner mit LW-Buchstaben versehen und benennen (21)

Frage von Xaero1982 zum Thema Microsoft ...

Netzwerkmanagement
gelöst Anregungen, kleiner Betrieb, IT-Umgebung (18)

Frage von Unwichtig zum Thema Netzwerkmanagement ...

Windows Update
Treiberinstallation durch Windows Update läßt sich nicht verhindern (17)

Frage von liquidbase zum Thema Windows Update ...