juergenl
Goto Top

Gültigkeit von Variablen in Batch-Dateien

Lokale - Globale - Variable

Guten Tag allerseits,

ich schlage mich mit folgendem Problem herum, das ich durch Experimentieren nicht lösen kann:

Ich leite eine Batchdatei mittlerer Größe (ich nenne sie hier "eins.bat") mit 'SetLocal EnableDelayedExpansion' ein, weil die meisten Variablen hier nur intern (LOKAL) von Bedeutung sind. Ich würde gerne aber EINE EINZIGE davon in den Bereich GLOBALER Variablen "hinüberretten", um sie auch nach Ende der Batchprozedur noch einmal zu verwenden. Ich kriege das aber nicht gebacken, muß auch gestehen daß ich die Auswirkungen von 'SetLocal ... ' leider nicht richtig verstanden habe.

Hat jemand bitte einen Tip für mich ?

Dazu möchte ich eine ergänzende Verständnisfrage stellen:

Wenn ich aus obiger Batchdatei ("eins.bat") eine weitere ("zwei.bat") per CALL aufrufe, dann bleiben zuvor LOKAL definierte Variable - nach meiner Beobachtung - zunächst auch in "zwei.bat" gültig. Ich kann sie aus "zwei.bat" heraus durchaus in eine Protokolldatei "zwei.txt" hineinschreiben.

Es gelingt offenbar aber nicht, diese Variable aus "zwei.bat" mit einem SET-Befehl GLOBAL zu verankern.

Es funkioniert: echo %korrzeit%>zwei.txt

Aber NICHT: SET kor1zeit=%korrzeit%

Was mach ich da wohl verkehrt, - oder muß ich die ganze Sache völlig anders aufziehen?

Danke im Voraus und beste Grüße

Jürgen

Content-Key: 28400

Url: https://administrator.de/contentid/28400

Printed on: June 20, 2024 at 20:06 o'clock

Member: djbrandt
djbrandt Mar 17, 2006 at 10:01:22 (UTC)
Goto Top
Hi,

jede Shell hat sein eigenes Environment. Wenn du eine Variable in einer Batch definierst und aus der Batch eine zweite Batch aufrufts (=2. Shell) dann ist diese Variable im Environment der 2. Batch vorhanden. Wenn Du im 2. Batch 1 Variable hinzufügst, bekommt das die erste Batch nicht mit.

Du hast 2 Alternativen:
aufruf der 2. Batch über

for /f "usebackq tokens=*" %%i in ('cmd /c zweit.bat variable1') do set korr1zeit = %%i
wenn Du in zweit.bat "echo korrzeit" als letzte Zeile einaust

oder

for /f "tokens=*" %%i in (zwei.txt) do set korr1zeit=%%i


oder die baust die 2. Batch als Prodezur in die erste Batch ein


eins.bat
...
...
...
set korr1zeit=%date%

call :zwei %korr1zeit%

set korr1zeit=%korrzeit%
...
...
...

goto ende
:zwei
set uerbergeben=%* (fängt auch leerzeichen ein)
rem mach was mit uebergeben
set korrzeit=Ergebnis der Berechnung
goto ende


da hast Du die Variablen in einer Shell


Müsste rein aus dem Gedächnis heraus so funktionieren.


Grüße

Dieter
Member: Juergenl
Juergenl Mar 17, 2006 at 10:29:53 (UTC)
Goto Top
Hi Dieter,

zunächst besten Dank!

Wenn Du im 2. Batch 1 Variable
hinzufügst, bekommt das die erste Batch
nicht mit.

DAS war auch nicht die Idee, daß die Batch 'eins.bat' diese Variable erfährt, denn den kennt sie ohnehin. Ich habe mir vielmehr die Sache mit der zweiten Batch nur deswegen einfallen lassen, weil ich darin ja eine neue GLOBALE Variable mit einem Rechenwert aus der Batch 'eins.bat' besetzen will.

Ich werde also jetzt in Abwandlung diesen Deinen Tip versuchen:

for /f "tokens=*" %%i in (zwei.txt) do set korr1zeit=%%i

denn in 'zwei.txt' sollte - auch nach meiner vorherigen Beobachtung - ja der gewünschte Wert enthalten sein.

Danach melde mich wieder,

So long

Gruß Jürgen
Member: Juergenl
Juergenl Mar 17, 2006 at 11:21:18 (UTC)
Goto Top
Hallo Dieter -

Heureka, - genau DAS ist der Schlüssel zum Problem:

Ich schreibe also jetzt in einem externen Einzeiler namens 'variable.bat' die LOKALE Variable, die ich GLOBAL machen will, in ein Textfile 'variable.txt'.

Ans Ende der Haupt-Batchdatei setze ich 'EndLocal' und als Abschluß darunter:

FOR /f "tokens=*" %%i IN (variable.txt) DO SET vglobale=%%i

Damit kann man also praktisch jede beliebige LOKALE Variable einzeln als GLOBALE herüber-retten.

Danke nochmal und beste Grüße

Jürgen
Member: Biber
Biber Mar 18, 2006 at 18:14:22 (UTC)
Goto Top
Nö,
auch wenn die Antwort geholfen hat... soooo umständlich und unlogisch ist Batch nun auch nicht.
Zur Verdeutlichung zwei Mini-Bätche:


:----snipp Batch1.bat
@echo off & setlocal
Set "AAAA=AAAA LOCAL gesetzt in Batch 1"
Set "BBBB=BBBB LOCAL gesetzt in Batch 1"
Echo ---in Batch1.bat ---gesetzte Variablen:
Set AAAA & Set BBBB
Echo ---in Batch1.bat --- Rufe "Batch2.bat AAAA"
Call Batch2.bat AAAA
echo ---wieder in Batch1.bat---- Variablen jetzt:
Set AAAA & Set BBBB
:----snapp Batch1.bat

:----snipp Batch2.bat
@echo off & setlocal
Echo In Batch2... überprüfe gesetzte Variablen "AAAA"/"BBBB"
Echo ---------Selbst noch nichts gesetzt...
Set AAAA & Set BBBB
Echo Set "AAAA=CCCC Lokaler Wert gesetzt in Batch2"
Set "AAAA=!!!!!!! Neuer Wert gesetzt in Batch2"
Echo Set "BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2"
Set "BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2"
Echo --------------Werte innerhalb von Batch2:
Set AAAA & Set BBBB
::Endlocal & Set "%1=!!! Auch Neu" & Set "BBBB=%BBBB%"
:----snapp Batch2.bat

Batch1 setzt zwei Variablen INNERHALB einer Setlocal-Struktur.
Batch zwei wird gerufen und verwendet die gleichen Variablennamen.

$cmd$batch1
---in Batch1.bat ---gesetzte Variablen:
AAAA=AAAA LOCAL gesetzt in Batch 1
BBBB=BBBB LOCAL gesetzt in Batch 1
---in Batch1.bat --- Rufe "Batch2.bat AAAA"
In Batch2... überprüfe gesetzte Variablen "AAAA"/"BBBB"
Selbst noch nichts gesetzt...
AAAA=AAAA LOCAL gesetzt in Batch 1
BBBB=BBBB LOCAL gesetzt in Batch 1
Set "AAAA=CCCC Lokaler Wert gesetzt in Batch2"
Set "BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2"
Werte innerhalb von Batch2:
AAAA=!!!!!!! Neuer Wert gesetzt in Batch2
BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2
---wieder in Batch1.bat---- Variablen jetzt:
AAAA=AAAA LOCAL gesetzt in Batch 1
BBBB=BBBB LOCAL gesetzt in Batch 1



> Erwähnenswert: Die Variablen AAAA und BBBB sind in Batch2 zwar bekannt,
aber Batch2 kann diese nicht so mit neuen Werten füllen, dass es für Batch1 gilt.

Wenn ich aber die auskommentierte Zeile ":: Endlocal &..." entkommentiere, geht das.

Ergebnis dann:
$cmd$batch1
---in Batch1.bat ---gesetzte Variablen:
AAAA=AAAA LOCAL gesetzt in Batch 1
BBBB=BBBB LOCAL gesetzt in Batch 1
---in Batch1.bat --- Rufe "Batch2.bat AAAA"
In Batch2... überprüfe gesetzte Variablen "AAAA"/"BBBB"
Selbst noch nichts gesetzt...
AAAA=AAAA LOCAL gesetzt in Batch 1
BBBB=BBBB LOCAL gesetzt in Batch 1
Set "AAAA=CCCC Lokaler Wert gesetzt in Batch2"
Set "BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2"
Werte innerhalb von Batch2:
AAAA=!!!!!!! Neuer Wert gesetzt in Batch2
BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2
---wieder in Batch1.bat---- Variablen jetzt:
AAAA=!!! Auch Neu
BBBB=!!!!!!! Lokaler Wert gesetzt in Batch2


Beide Syntax-Varianten habe ich auch in Produktiv-Bätchen im Einsatz.
Wem es jetzt einleuchtet, dass auch eine Anweisung wie 'Set "BBBB=%BBBB%"' Sinn machen kann, der hat es verstanden.
Lasst Euch also NICHT solche Anweisungen von übereifrigen Praktikanten wieder rauslöschen.

Ebenfalls elegant bei mehreren "global bekanntzumachenden Variablen" ist die Zeile:

Endlocal & for %%i in ("var1=%var1%" "var2=%var2%" ..) do set %%i

Alles klar? *gg

Schönes Wochenende
Biber
Member: djbrandt
djbrandt Mar 18, 2006 at 21:30:39 (UTC)
Goto Top
tja,

man lernt nie aus face-smile das ist ja das schöne an der IT

Ich bin immer davon ausgegangen, das Änderungen an Variablen nicht an die Parentshell zurückgegeben werden.

Jetzt verstehe ich auch den Sinn von setlocal face-smile))

Wobei ich es möglichst vermeide 2 Batches zu verwenden, seitdem ich gelernt habe, dass es auch bei batches Prozeduren gibt.


Grüße

Dieter
Member: Biber
Biber Mar 18, 2006 at 22:06:48 (UTC)
Goto Top
@djbrandt
Wobei ich es möglichst vermeide 2 Batches zu verwenden, seitdem ich gelernt habe, dass es auch bei batches Prozeduren gibt.
...oder, wie ich es formulieren würde: Es ist schon schwierig genug, einen Batch zum Fliegen zu bringen...

Ich jedenfalls habe meist schon Schwierigkeiten bei mittelkomplexen Onelinern...
...und zwei miteinander globale Variable austauschende Bätche überlasse ich lieber den Profis.. *gg

Schönen Abend
Biber
Member: Juergenl
Juergenl Mar 25, 2006 at 12:01:52 (UTC)
Goto Top
Hej miteinander,

ich melde mich mit einiger Verspätung zum Thema und danke für alle Mühen!

umständlich und unlogisch ist Batch nun auch nicht.

UNLOGISCH ganz sicher nicht, wobei zwar die "Logik" oft nur schwer zu durchschauen ist. In solchen Fällen ist ein erhebliches Maß an Abstraktionsvermögen gefordert. UMSTÄNDLICH würde ich es dennoch nicht nennen.

Zur Verdeutlichung zwei Mini-Bätche:

Dafür mein besonderer Dank!

:----snipp Batch1.bat ...........
:----snapp Batch2.bat ........

... gründlich nachempfunden, - auch soweit verstanden, daß ich es *leidlich* weitererklären könnte ... *g*

Dennoch fehlern mir immer noch ein paar Grundlagen

$cmd$batch1

- hier zum Beispiel die Einkleidung von Befehlen in Dollarzeichen; an anderen Stellen auch die Voranstellung von Klammeraffen ...

Deine einschlägige Regel mit den Anführungszeichen habe ich "ein bißchen verstanden".


Alles klar? *gg

... na, sagen wir die Hälfte!

Danke nochmal und beste Grüße zum Wochenende

Jürgen