multiple Instanzen organisieren mit globalen Variablen ?
mit endlocal & set zur parentshell - aber zur unabhängigen batch ??
Hallo.
Ich wollte erst in den Thread "Gültigkeit von Vars..." schreiben, habe dann aber gemerkt, dass mein Problemchen wohl doch zu komplex wird.
Dort habe ich zwar verstanden, wie ich eine Variable der "Parentshell" übergeben kann, würde das aber auch gern bei unabhängigen batchen verwenden. Bzw möchte ich folgendes erreichen... (the whole story: )
Eine batch "launch.bat" die über WinXP mit einer Dateierweiterung (*.dem) verknüpft ist, wird durch den Doppelklick auf so eine .dem Datei aufgerufen. Nach einigen Operationen startet sie eine Anwendung und übergibt ihr die .dem als Parameter:
start app.exe %~nx1
Nun will ich aber mehr als eine .dem markieren und starten. WinXP führt aber leider bei dieser Aktion
start launch.bat %1
start launch.bat %1
start launch.bat %1
aus und nicht
start launch.bat %1 %2 %3
Und nun zum topic:
Meine Idee war, dass die launch.bat beim 1. Start eine globale Variable setzt (damit eine 2. Instanz der launch.bat dort nachgucken kann) und jeder weitere (gleichzeitige) Start der launch.bat nur zur Erzeugung einer globalen Var aus dem Parameter führt. zB so:
if NOT defined apprun (
Endlocal & set "apprun=1"
setlocal
) else (
Endlocal & set "globvar%apprun%=%~nx1"
exit
)
::weiter im Text nur dei der 1. Instanz
::nach ca 2 Sekunden Laufzeit:
start app.exe %~nx1 %globvar1% %globvar2% %globvar3% ...
:bis max 8 params sollen möglich sein)
Die globvars werden nur übergeben, wenn mehr als eine Datei markiert wurde. Theoretisch. Praktisch funktioniert das mit den globalen Vars nur, wenn sich die launch.bat selber aufgerufen hat. Gibt es also eine Möglichkeit, Vars für eine 2., manuell gestartete batch bekannt zu machen ? Und wenn ja - wie ?
Die Lösung mit einer txt datei als globale var kam mir auch schon in den Sinn; wäre allerdings zu langsam (und außerdem kommt es vor, dass die launch.bat vorzeitig beendet wird und die .txt nicht mehr gelöscht werden kann = Probleme beim nächsten Start)
Letzter Ausweg wäre vielleicht, dass eine weitere Instanz die .txt nur dann zum Speichern ihrer Parameter akzeptiert, wenn sie in den letzten 2 Sekunden erstellt wurde.
Naja ich hoffe ihr habt mich verstanden und könnt helfen.
mfg, yashi
Hallo.
Ich wollte erst in den Thread "Gültigkeit von Vars..." schreiben, habe dann aber gemerkt, dass mein Problemchen wohl doch zu komplex wird.
Dort habe ich zwar verstanden, wie ich eine Variable der "Parentshell" übergeben kann, würde das aber auch gern bei unabhängigen batchen verwenden. Bzw möchte ich folgendes erreichen... (the whole story: )
Eine batch "launch.bat" die über WinXP mit einer Dateierweiterung (*.dem) verknüpft ist, wird durch den Doppelklick auf so eine .dem Datei aufgerufen. Nach einigen Operationen startet sie eine Anwendung und übergibt ihr die .dem als Parameter:
start app.exe %~nx1
Nun will ich aber mehr als eine .dem markieren und starten. WinXP führt aber leider bei dieser Aktion
start launch.bat %1
start launch.bat %1
start launch.bat %1
aus und nicht
start launch.bat %1 %2 %3
Und nun zum topic:
Meine Idee war, dass die launch.bat beim 1. Start eine globale Variable setzt (damit eine 2. Instanz der launch.bat dort nachgucken kann) und jeder weitere (gleichzeitige) Start der launch.bat nur zur Erzeugung einer globalen Var aus dem Parameter führt. zB so:
if NOT defined apprun (
Endlocal & set "apprun=1"
setlocal
) else (
Endlocal & set "globvar%apprun%=%~nx1"
exit
)
::weiter im Text nur dei der 1. Instanz
::nach ca 2 Sekunden Laufzeit:
start app.exe %~nx1 %globvar1% %globvar2% %globvar3% ...
:bis max 8 params sollen möglich sein)
Die globvars werden nur übergeben, wenn mehr als eine Datei markiert wurde. Theoretisch. Praktisch funktioniert das mit den globalen Vars nur, wenn sich die launch.bat selber aufgerufen hat. Gibt es also eine Möglichkeit, Vars für eine 2., manuell gestartete batch bekannt zu machen ? Und wenn ja - wie ?
Die Lösung mit einer txt datei als globale var kam mir auch schon in den Sinn; wäre allerdings zu langsam (und außerdem kommt es vor, dass die launch.bat vorzeitig beendet wird und die .txt nicht mehr gelöscht werden kann = Probleme beim nächsten Start)
Letzter Ausweg wäre vielleicht, dass eine weitere Instanz die .txt nur dann zum Speichern ihrer Parameter akzeptiert, wenn sie in den letzten 2 Sekunden erstellt wurde.
Naja ich hoffe ihr habt mich verstanden und könnt helfen.
mfg, yashi
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 28704
Url: https://administrator.de/contentid/28704
Ausgedruckt am: 05.11.2024 um 13:11 Uhr
8 Kommentare
Neuester Kommentar
Hmm, yashi,
ich hatte Deine Frage nicht überlesen... aber da musste ich mir auch Bedenkzeit ausbitten.
Vorläufiges Ergebnis meiner Meditation:
Drei Strategien würden mir einfallen, eine davon geht nicht.
Erste Variante
Was nicht geht, ist das Lesen einen "Globalen Variablen", auf die jede CMD-Instanz zugreufen kann.
Das heißt, Setzen einer "Globalen Variablen" geht zwar mit "SetX.exe", aber... zwei Probleme
- Du kommst von der bereits aktiven Instanz der CMD.exe nie wieder lesend dran.
- Änderungen dieser globalen Variablen gelten nicht für alle aktiven Instanzen.
Simples Beispiel:
Du kannst natürlich auch Variablen wie %cd% (aktuelles Verzeichnis) oder %prompt% in einer von mehreren offenen CMD-Instanzen ändern und auch mit SetX.exe für jede neue Instanz vorgeben, aber:
- eine Änderung der %prompt%s wird ja auch nicht "nachgelesen"/ in allen CMD-Instanzen aktiv
- und keine der Änderungen gilt für CMD.exe's, die Du selber vom CMD-Prompt startest. Da gilt DEIN aktuelles Environment.
...geht nicht, geht nicht, geht nicht... no chance.
Zweite Variante...wie es alle Windows-Programme machen:
Es gibt nur einen Ort im ganzen Windows-Gelumpe, wo Informationen EINmalig und EINdeutig stehen... genau, die Registry.
Das würde funktionieren...aber das wäre mir zu aufwändig und zu dauerhaft.
Dritte Variante
Über eine Datei persistieren.
Das geht relativ sicher
Meiner Meinung nach ist diese Prüfung "nicht älter als zwei Minuten" überflüssig - genau genommen ist diese Prüfung das aufregendste und längste am ganzen Batch.
So würde ein "launch.bat" aussehen können:
Hier nochmal mit der "Nicht-älter-als-2-Minuten-Prüfung"
Damit würde die von Dir angestrebte Mimik funktionieren (probiers mit Markieren von 3 *.dem-Files im Explorer; vorher Pfade anpassen).
Bin zwar offen für andere Strategien, aber ich wüsste keine andere.
Die Aufgabe an einen Dienst/Service zu delegieren, der zwei, drei Sekunden wartet, bis alle Aufrufe und alle Parameter eingetrudelt sind, wäre IMHO noch aufwändiger.
Grüße
Biber
ich hatte Deine Frage nicht überlesen... aber da musste ich mir auch Bedenkzeit ausbitten.
Vorläufiges Ergebnis meiner Meditation:
Drei Strategien würden mir einfallen, eine davon geht nicht.
Erste Variante
Was nicht geht, ist das Lesen einen "Globalen Variablen", auf die jede CMD-Instanz zugreufen kann.
Das heißt, Setzen einer "Globalen Variablen" geht zwar mit "SetX.exe", aber... zwei Probleme
- Du kommst von der bereits aktiven Instanz der CMD.exe nie wieder lesend dran.
- Änderungen dieser globalen Variablen gelten nicht für alle aktiven Instanzen.
Simples Beispiel:
Du kannst natürlich auch Variablen wie %cd% (aktuelles Verzeichnis) oder %prompt% in einer von mehreren offenen CMD-Instanzen ändern und auch mit SetX.exe für jede neue Instanz vorgeben, aber:
- eine Änderung der %prompt%s wird ja auch nicht "nachgelesen"/ in allen CMD-Instanzen aktiv
- und keine der Änderungen gilt für CMD.exe's, die Du selber vom CMD-Prompt startest. Da gilt DEIN aktuelles Environment.
...geht nicht, geht nicht, geht nicht... no chance.
Zweite Variante...wie es alle Windows-Programme machen:
Es gibt nur einen Ort im ganzen Windows-Gelumpe, wo Informationen EINmalig und EINdeutig stehen... genau, die Registry.
Das würde funktionieren...aber das wäre mir zu aufwändig und zu dauerhaft.
Dritte Variante
Über eine Datei persistieren.
Das geht relativ sicher
Meiner Meinung nach ist diese Prüfung "nicht älter als zwei Minuten" überflüssig - genau genommen ist diese Prüfung das aufregendste und längste am ganzen Batch.
So würde ein "launch.bat" aussehen können:
::--snipp launch.bat
@echo off
:: Parameter1 [%1] ein *.dem-File
set "demtodo=%temp%\demToDo.lst"
echo %1>>%demtodo%
ping -n 2 localhost>nul
for /f %%a in (%demtodo%) do call :setAllpara %%a
:: wenn die erste gefundene *.dem-Datei gleich dem Parameter 1 ist..
:: dann hat dieser bat den Job zu tun
IF [%firstdem%]==[%1] (
del /q %demtodo%
echo ICH rufe app %allpara%
:: hier dann: c:\appdir\app.exe %allpara%
pause
)
exit
:setallpara
if not defined Firstdem set "Firstdem=%1"
set allpara=%allpara% %1
goto :eof
:: ---snapp launch.bat
::--snipp launch.bat
@echo off & setlocal
:: Parameter1 [%1] ist ein *.dem-File
set "demtodo=%temp%\demToDo.lst"
If exist %DemTodo% call :CheckIfOld
echo %1>>%demToDo%
ping -n 2 localhost>nul
for /f %%a in (%demToDo%) do call :setAllpara %%a
:: wenn die erste gefundene *.dem-Datei gleich dem Parameter 1 ist..
:: dann hat dieser bat den Job zu tun
IF [%firstdem%]==[%1] (
del /q %DemToDo%
echo ICH rufe app %allpara%
:: hier dann: c:\appdir\app.exe %allpara%
pause
)
exit
:setallpara
if not defined Firstdem set "Firstdem=%1"
set allpara=%allpara% %1
goto :eof
:CheckIfOld
for /f %%a in ('dir /b /s %demtodo%') do (
for /f "tokens=2-3 delims=: " %%i in ("%%~ta") do Set /a "FileMins=%%i*60+%%j")
for /f "tokens=1-2 delims=:," %%i in ("%time%") do Set /a "TimeMins=%%i*60+%%j"
rem Echo filemins: %filemins% timemins: %timemins%
set /a timediff=%TimeMins%-%FileMins%
if %timediff% gtr 2 echo %demTodo% ist %timediff% Minuten alt.
if %timediff% gtr 2 del /q %demTodo%
pause
goto :eof
:: ---snapp launch.bat
Damit würde die von Dir angestrebte Mimik funktionieren (probiers mit Markieren von 3 *.dem-Files im Explorer; vorher Pfade anpassen).
Bin zwar offen für andere Strategien, aber ich wüsste keine andere.
Die Aufgabe an einen Dienst/Service zu delegieren, der zwei, drei Sekunden wartet, bis alle Aufrufe und alle Parameter eingetrudelt sind, wäre IMHO noch aufwändiger.
Grüße
Biber
Moin yashi,
tja, die Kröte mit dem Zeitverlust wirst Du wohl schlucken müssen..
Es gibt keine Chance, dass Du einen Zähler, den eine "parallele" andere CMD-Instanz von 41 auf 42 hochgesetzt hat, irgendwie auslesen kannst.
Zu Deinen Fragen (danke fürs aufmerksame Lesen):
ad 1)
Die "DelayedExpansion" braucht man/frau nur in den Fällen, in denen
...bei dem ja NIE "Es funktioniert!" geschrieben wird.
Weil: der CMD löst beim Einlesen der "IF (..)"-Anweisung EINmalig die Variable %VAR% auf.
- oder gib mir einen Substring einer Variablen von einer variablen Position an. [ !var:~%pos%! ]
Die Zeile
ist auch für die CMD.exe EINE Zeile, auch wenn dort ein "Call: blah" aufgerufen wird
Wenn ich irgendetwas unleserliches hätte zusammentrümmern wollen, hätte ich auch mit...
...das Ganze in einer (formatierten) Zeile schreiben können - ohne "Call: blah"
Ich fand es mit "call" leserlicher/wartbarer.
Und in eine Zeile bekomm ich es hier im Forum eh nicht... *g
zu 3)
Das "dir /b /s %demtodo%".....ja, erwischt....
Ich habe den (scheinbar überflüssigen) Parameter "/s" genommen, weil...
Microsoft kann noch schlechter programmieren als ich.
(Die Verleumdungslage riskier ich jetzt mal).
Mach mal folgendes (wortwörtlich/nichts anzupassen) am CMD-Prompt:
Na ja, M$ halt... gottseidank werden die wohl nicht die Fußball-WM übertragen...
ad 4)
Ja. Jein.
So würde ich es machen.. noch kürzer. Ich will doch eine leere Datei haben ... nicht eine mit Parameter 1.
Grüße und viel Spaß beim Experimentieren.
Biber
tja, die Kröte mit dem Zeitverlust wirst Du wohl schlucken müssen..
Es gibt keine Chance, dass Du einen Zähler, den eine "parallele" andere CMD-Instanz von 41 auf 42 hochgesetzt hat, irgendwie auslesen kannst.
Zu Deinen Fragen (danke fürs aufmerksame Lesen):
ad 1)
muss man innerhalb von subroutinen (:call) nicht trozdem !allpara! verwenden ?
dachte DelayedExpansion lässt sich nur mit goto umgehen ?
Nein. "Call :sub"-Routinen sind eigentlich anderen Batchdateien vergleichbar, die mit "Call AndererBatch.bat" aufgerufen werden.dachte DelayedExpansion lässt sich nur mit goto umgehen ?
Die "DelayedExpansion" braucht man/frau nur in den Fällen, in denen
- der CMD-Interpreter einen ganzen (aus Lesbarkeitsgründen mehrzeiligen) Block als eine Zeile einliest
set VAR=vorher
if "%VAR%" == "vorher" (
set VAR=nachher;
if "%VAR%" == "nachher" @echo Es funktioniert!
)
Weil: der CMD löst beim Einlesen der "IF (..)"-Anweisung EINmalig die Variable %VAR% auf.
- den andere Fall,wo es nötig ist, sind die Variablen-in-Variablen wie
- oder gib mir einen Substring einer Variablen von einer variablen Position an. [ !var:~%pos%! ]
- oder in dem Fall, das eine frisch gesetzte Variable noch in gleichen Zeile umgeformt werden muss
Die Zeile
for /f %%a in (%demToDo%) do call :setAllpara %%a
Wenn ich irgendetwas unleserliches hätte zusammentrümmern wollen, hätte ich auch mit...
for /f %%a in (%demToDo%) do (
set allpara=!allpara! %%a
if not defined FirstDem set FirstDem=%%a
)
Ich fand es mit "call" leserlicher/wartbarer.
Und in eine Zeile bekomm ich es hier im Forum eh nicht... *g
zu 3)
Das "dir /b /s %demtodo%".....ja, erwischt....
Ich habe den (scheinbar überflüssigen) Parameter "/s" genommen, weil...
Microsoft kann noch schlechter programmieren als ich.
(Die Verleumdungslage riskier ich jetzt mal).
Mach mal folgendes (wortwörtlich/nichts anzupassen) am CMD-Prompt:
$cmd$for /f %i in ('dir /b %temp%\*.tmp') do @echo %~nxi
(....alle Dateien *.tmp werden mit Namen und Endung aufgelistet)
$cmd$for /f %i in ('dir /b %temp%\*.tmp') do @echo %~nxi %~ti
(....alle Dateien *.tmp werden mit Namen und Endung aufgelistet) *stutz -Nanu????
$cmd$for /f %i in ('dir /b /s %temp%\*.tmp') do @echo %~nxi %~ti
(....alle Dateien *.tmp werden mit Namen, Endung und Änderungsdatum aufgelistet) ?????Nanu????
Na ja, M$ halt... gottseidank werden die wohl nicht die Fußball-WM übertragen...
ad 4)
Die Zeile mit dem del /q in :CheckIfOld könnte man vielleicht auch durch
> echo %1>%demToDo%
>
Ja. Jein.
echo.>%demToDo%
Grüße und viel Spaß beim Experimentieren.
Biber