Errorlevel Syntax? Robocopy Fehlerauswertung geht nicht
Servus Leute,
wer kann Helfen???
System W2K3 und Win7
1. wie ist die richtige Syntax von ERRORLEVEL ?
z.B.
IF ERRORLEVEL 2 ECHO ##Fehler größer 2## ?
mit Robocopy hab ich Probleme die Fehlerauswertung geht nicht
hier der Soucecode.. die PROCEDURE DIE NICHT geht !!! ich bekomme immer als Ergebnis:NOERR 00 NO CHANGE
und ERRORLEVEL 0 was ist Falsch ???
wer kann Helfen???
System W2K3 und Win7
1. wie ist die richtige Syntax von ERRORLEVEL ?
z.B.
IF ERRORLEVEL 2 ECHO ##Fehler größer 2## ?
mit Robocopy hab ich Probleme die Fehlerauswertung geht nicht
hier der Soucecode.. die PROCEDURE DIE NICHT geht !!! ich bekomme immer als Ergebnis:NOERR 00 NO CHANGE
und ERRORLEVEL 0 was ist Falsch ???
REM *** ROBOCOPY FÜR ALLES +FEHLERAUSWERTUNG INS LOG **************************************************************************************
REM ### Var: %P_Robo_Path_Von% # VON WO KOPIERT WERDEN SOLL NUR PATH C:\TEST\ ###
REM ### Var: %P_Robo_Path_Nach% # WOHIN WIRD KOPIERT WERDEN SOLL NUR PATH C:\TEST\ ###
REM ### Var: %P_Robo_FileS% # ZU KOPIERENDE FILES *.* für alle z.B datei.txt ###
REM ### Var: %P_Robo_Para% # PARAMETERÜBERGABE AN ROBOCOPY Z.B /E / PURGE /MIR ###
REM ### Var: %P_Robo_MSG_OK% # FEHLERMELDUNG OK-TEXT DER BEI FEHLER VERWENDET WIRD ###
REM ### Var: %P_Robo_MSG_ERR% # FEHLERMELDUNG ERR-TEXT DER BEI FEHLER VERWENDET WIRD ###
:ProRobocopy4Var
REM --- WRITE LOGFILE IST VORHANDEN ALSO INS LOGFILE SCHREIBEN ---
ROBOCOPY %P_Robo_Path_Von% %P_Robo_Path_Nach% %P_Robo_FileS% %P_Robo_Para% /IS /W:2 /R:10 /COPY:DAT /V /TEE
IF ERRORLEVEL 17 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 17 ***ERROR ?? ***"
IF ERRORLEVEL 16 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 16 ***FATAL ERROR***"
IF ERRORLEVEL 15 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 15 FAIL MISM XTRA COPY"
IF ERRORLEVEL 14 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 14 FAIL MISM XTRA"
IF ERRORLEVEL 13 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 13 FAIL MISM COPY"
IF ERRORLEVEL 12 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 12 FAIL MISM"
IF ERRORLEVEL 11 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 11 FAIL XTRA COPY"
IF ERRORLEVEL 10 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 10 FAIL XTRA"
IF ERRORLEVEL 9 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 09 FAIL COPY"
IF ERRORLEVEL 8 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 08 FAIL"
IF ERRORLEVEL 7 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 07 MISM XTRA COPY"
IF ERRORLEVEL 6 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 06 MISM XTRA"
IF ERRORLEVEL 5 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 05 MISM COPY"
IF ERRORLEVEL 4 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 04 MISM"
IF ERRORLEVEL 3 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 03 XTRA COPY"
IF ERRORLEVEL 2 SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS: ERR 02 XTRA"
REM ### SONDERFäLLE 0 u 1 SIND KEINE FEHLER ###
IF ERRORLEVEL 1 SET "MsgInfoSwap=%Msg_OK%ROCOPY:STATUS: NOERR 01 COPY"
IF ERRORLEVEL 0 SET "MsgInfoSwap=%Msg_OK%ROCOPY:STATUS: NOERR 00 NO CHANGE"
ECHO ### %ERRORLEVEL% der ist immer 0 ?????####
REM --- ROBOCOPY STATUS auf Bildschirm ---
IF ERRORLEVEL 2 (
ECHO ROCOPY: Fehler STATUS: %MsgInfoSwap% beim kopieren %P_Robo_FileS% ERR:%ERRORLEVEL% !."
) ELSE (
echo ROCOPY: STATUS: %MsgInfoSwap% FILES: %P_Robo_FileS% wurden kopiert!."
)
GOTO :EOF
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 223631
Url: https://administrator.de/contentid/223631
Ausgedruckt am: 22.11.2024 um 09:11 Uhr
19 Kommentare
Neuester Kommentar
Hallo Viper-Berlin,
du solltest dir das hier mal durchlesen: http://hannes-schurig.de/26/08/2010/batch-if-errorlevel/
Der Vergleich ohne operator wie du ihn machst könnte man quasi so lesen:
Geprüft wird also nicht if errorlevel = X sondern if errorlevel >= X!
da bei dir der letzte Vergleich, der mit dem ERRORLEVEL 0 ist, wird die Variable immer mit "NOERR 00 NO CHANGE" versehen.
mach den Vergleich mit ERRORLEVEL also besser so:
usw.
Grüße Uwe
du solltest dir das hier mal durchlesen: http://hannes-schurig.de/26/08/2010/batch-if-errorlevel/
Der Vergleich ohne operator wie du ihn machst könnte man quasi so lesen:
WENN ERRORLEVEL >= 0
Geprüft wird also nicht if errorlevel = X sondern if errorlevel >= X!
da bei dir der letzte Vergleich, der mit dem ERRORLEVEL 0 ist, wird die Variable immer mit "NOERR 00 NO CHANGE" versehen.
mach den Vergleich mit ERRORLEVEL also besser so:
IF "%ERRORLEVEL%" == "17" SET ....
Grüße Uwe
mach es so:
Du speicherst nach dem Robocopy-Befehl den ERRORLEVEL-Wert in einer eigenen VARIABLEN und überprüfst dann nur noch diese nacheinander:
Du speicherst nach dem Robocopy-Befehl den ERRORLEVEL-Wert in einer eigenen VARIABLEN und überprüfst dann nur noch diese nacheinander:
ROBOCOPY %P_Robo_Path_Von% %P_Robo_Path_Nach% %P_Robo_FileS% %P_Robo_Para% /IS /W:2 /R:10 /COPY:DAT /V /TEE
set FEHLERCODE=%ERRORLEVEL%
IF "%FEHLERCODE%"=="17" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 17 *ERROR ?? *"
usw.
....
...
bitte benutze Tags um deinen Code zu posten, sonst gehen hier vielleicht wichtige Sonderzeichen unter !!
mach mal bitte die Umleitung der Ausgaben von Robocopy weg :
mach mal bitte die Umleitung der Ausgaben von Robocopy weg :
>NUL
Hallo,
zunächst war Dein erster Ansatz bzgl. der Auswertung schon korrekt. Allerdings sollte der Setbefehl meines Wissens nach so lauten?
Und schau Dir mal folgende Seite an ROBOCOPY Exit Codes
Gruss Penny.
zunächst war Dein erster Ansatz bzgl. der Auswertung schon korrekt. Allerdings sollte der Setbefehl meines Wissens nach so lauten?
IF ERRORLEVEL 17 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 17 *ERROR ?? *"
IF ERRORLEVEL 16 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 16 *FATAL ERROR*"
IF ERRORLEVEL 15 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 15 FAIL MISM XTRA COPY"
IF ERRORLEVEL 14 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 14 FAIL MISM XTRA"
IF ERRORLEVEL 13 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 13 FAIL MISM COPY"
IF ERRORLEVEL 12 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 12 FAIL MISM"
IF ERRORLEVEL 11 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 11 FAIL XTRA COPY"
IF ERRORLEVEL 10 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 10 FAIL XTRA"
IF ERRORLEVEL 9 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 09 FAIL COPY"
IF ERRORLEVEL 8 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 08 FAIL"
IF ERRORLEVEL 7 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 07 MISM XTRA COPY"
IF ERRORLEVEL 6 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 06 MISM XTRA"
IF ERRORLEVEL 5 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 05 MISM COPY"
IF ERRORLEVEL 4 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 04 MISM"
IF ERRORLEVEL 3 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 03 XTRA COPY"
IF ERRORLEVEL 2 SET MsgInfoSwap="%Msg_ERR%ROCOPY:STATUS: ERR 02 XTRA"
Und schau Dir mal folgende Seite an ROBOCOPY Exit Codes
Gruss Penny.
Moin,
Helpfile zu "IF" bezüglich Errorlevel:
ERRORLEVEL Nummer --> Bedingung ist erfüllt, wenn das zuletzt ausgeführte Programm einen Code größer oder gleich der Nummer zurückgibt.
Laut Deinem Script wird in Zeile 17 bzw. 21 der ROBOCOPY-Befehl ausgeführt.
In Zeile 22 folgt ein SET-Befehl.
Die Rückgabewert welchen Befehls wird nun in ERRORLEVEL enthalten sein?
Außerdem willst Du doch mit SET eine Variable füllen, aber welche geht aus Deinem Script nicht hervor (siehe Post von P.C).
Gruß J chem
Helpfile zu "IF" bezüglich Errorlevel:
ERRORLEVEL Nummer --> Bedingung ist erfüllt, wenn das zuletzt ausgeführte Programm einen Code größer oder gleich der Nummer zurückgibt.
Laut Deinem Script wird in Zeile 17 bzw. 21 der ROBOCOPY-Befehl ausgeführt.
In Zeile 22 folgt ein SET-Befehl.
Die Rückgabewert welchen Befehls wird nun in ERRORLEVEL enthalten sein?
Außerdem willst Du doch mit SET eine Variable füllen, aber welche geht aus Deinem Script nicht hervor (siehe Post von P.C).
Gruß J chem
so müsste es laufen:
Stichwort: delayed expansion
setlocal ENABLEDELAYEDEXPANSION
REM *** ROBOCOPY FÜR ALLES +FEHLERAUSWERTUNG INS LOG **************************************************************************************
REM ### Var: %P_Robo_Path_Von% # VON WO KOPIERT WERDEN SOLL NUR PATH C:\TEST\ ###
REM ### Var: %P_Robo_Path_Nach% # WOHIN WIRD KOPIERT WERDEN SOLL NUR PATH C:\TEST\ ###
REM ### Var: %P_Robo_FileS% # ZU KOPIERENDE FILES *.* FÜR ALLE Z.B DATEI.TXT ###
REM ### Var: %P_Robo_Para% # PARAMETERÜBERGABE AN ROBOCOPY Z.B /E / PURGE /MIR ###
:ProRobocopy4Var
SET /A "Err_Robo=0" & REM *** ERRORVARIABLE VON ROBOCOPY AUF 0 SETZEN ***
SET "MsgInfoSwap=%Msg_OK%ROCOPY: WAS:%P_Robo_FileS%"
CALL :ProMsgWriteToScrAndLog
SET "MsgInfoSwap=%Msg_OK%ROCOPY: VON:%P_Robo_Path_Von%"
CALL :ProMsgWriteToScrAndLog & REM *** CREATE INFO -MSG TO SCR UND LOG- ***
SET "MsgInfoSwap=%Msg_OK%ROCOPY: NACH:%P_Robo_Path_Nach%"
CALL :ProMsgWriteToScrAndLog & REM *** CREATE INFO -MSG TO SCR UND LOG- ***
IF /I "%LogF_Full_Main_Swap%"=="NUL" (
REM --- NOT WRITE LOGFILE IST NICHT VORHANDEN ALSO NICHT REIN SCHREIBEN AUSGABE IN NULL UMLEITEN ---
ROBOCOPY %P_Robo_Path_Von% %P_Robo_Path_Nach% %P_Robo_FileS% %P_Robo_Para% /IS /W:2 /R:10 /COPY:DAT /V /TEE >NUL
SET /A "FEHLERCODE=!ERRORLEVEL!" & REM *** FEHLER in VARIABLE SPEICHERN ***
) ELSE (
REM --- WRITE LOGFILE IST VORHANDEN ALSO INS LOGFILE SCHREIBEN ---
ROBOCOPY %P_Robo_Path_Von% %P_Robo_Path_Nach% %P_Robo_FileS% %P_Robo_Para% /IS /W:2 /R:10 /COPY:DAT /V /TEE /LOG+:"%LogF_Full_Main%" >NUL
SET /A "FEHLERCODE=!ERRORLEVEL!" & REM *** FEHLER in VARIABLE SPEICHERN ***
)
ECHO ##### vorher FEHLERCODE=!FEHLERCODE!######
IF "!FEHLERCODE!" == "17" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 17 ***ERROR ?? ***"
IF "!FEHLERCODE!" == "16" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 16 ***FATAL ERROR***"
IF "!FEHLERCODE!" == "15" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 15 FAIL MISM XTRA COPY"
IF "!FEHLERCODE!" == "14" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 14 FAIL MISM XTRA"
IF "!FEHLERCODE!" == "13" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 13 FAIL MISM COPY"
IF "!FEHLERCODE!" == "12" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 12 FAIL MISM"
IF "!FEHLERCODE!" == "11" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 11 FAIL XTRA COPY"
IF "!FEHLERCODE!" == "10" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 10 FAIL XTRA"
IF "!FEHLERCODE!" == "9" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 09 FAIL COPY"
IF "!FEHLERCODE!" == "8" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 08 FAIL"
IF "!FEHLERCODE!" == "7" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 07 MISM XTRA COPY"
IF "!FEHLERCODE!" == "6" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 06 MISM XTRA"
IF "!FEHLERCODE!" == "5" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 05 MISM COPY"
IF "!FEHLERCODE!" == "4" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 04 MISM"
IF "!FEHLERCODE!" == "3" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 03 XTRA COPY"
IF "!FEHLERCODE!" == "2" SET "MsgInfoSwap=%Msg_ERR%ROCOPY:STATUS:ERR 02 XTRA"
REM --- SIND KEIN FEHLER 0 DATEIEN SIND SCHON VORHANDEN 1 KOPIERT ---
IF "!FEHLERCODE!" == "1" SET "MsgInfoSwap=%Msg_OK%ROCOPY:STATUS:NOERR 01 COPY"
IF "!FEHLERCODE!" == "0" SET "MsgInfoSwap=%Msg_OK%ROCOPY:STATUS:NOERR 00 NO CHANGE"
ECHO ##### nachher FEHLERCODE=!FEHLERCODE! ######
CALL :ProMsgWriteToScrAndLog & REM *** CREATE INFO -MSG TO SCR UND LOG- ***
REM --- ROBOCOPY STATUS IN MSG SCHREIBEN WENN ERRORLEVEL >=2 DANN FEHLERMELDUNG ANSONSTEN CHECKEN OB KOPIERT WURDE O ÜBERSPRUNGEN---
IF "!FEHLERCODE!" GEQ "2" (
SET /A "Err_Robo=1" & REM *** Err_Robo FÜR DIE AUSWERTUNG VON FEHLERN BEI ROBOCOPY ***
SET "MsgInfoSwap=%Msg_ERR%ROCOPY: Fehler beim kopieren %P_Robo_FileS% ERR:!FEHLERCODE! ."
CALL :ProEventLogCreateERR & REM *** CREATE EVENT ERROR ***
) ELSE (
IF "!FEHLERCODE!" == "1" (
SET "MsgInfoSwap=%Msg_OK%ROCOPY: FILES: %P_Robo_FileS% wurden kopiert."
)
IF "!FEHLERCODE!" == "0" (
SET "MsgInfoSwap=%Msg_WAR%ROCOPY: FILES: %P_Robo_FileS% wurden übersprungen."
)
CALL :ProMsgWriteToScrAndLog & REM *** CREATE INFO -MSG TO SCR UND LOG- ***
)
)
Zitat von @Viper-Berlin:
ich hätte noch ein paar Fragen dazu hat diese
also was lokale u globale Variablen sind ist klar aber wozu braucht man diesen Befehl
setlocal ENABLEDELAYEDEXPANSION
Tutorial zur FOR-Schleifeich hätte noch ein paar Fragen dazu hat diese
also was lokale u globale Variablen sind ist klar aber wozu braucht man diesen Befehl
setlocal ENABLEDELAYEDEXPANSION
Hat der auswirkungen auf meine anderen globalen Variablen ???
nur wenn etwas mit zwei Ausrufezeichen umschlossen istwie kann man es beenden ?
setlocal DISABLEDELAYEDEXPANSION
wie kann ich das Script so schreiben das es funktioniert wie in jeder anderen Programmiersprache ?
eine andere Programmiersprache bzw. Scriptsprache benutzen anstatt noch immer auf Batch zu setzen....
Hallo Zusammen.
Der Errorlevelwert von ROBOCOPY ist genau genommen eine Bitmaske, in der einzelne Fehlerflags gesetzt sind. Genau so kann man also auch die einzelnen Flags checken, nämlich mittels bitweisen Operationen. Eine kleine Subroutine genügt, um nicht jeden einzelnen Errorlevelwert gesondert behandeln zu müssen.
Grüße
rubberman
Der Errorlevelwert von ROBOCOPY ist genau genommen eine Bitmaske, in der einzelne Fehlerflags gesetzt sind. Genau so kann man also auch die einzelnen Flags checken, nämlich mittels bitweisen Operationen. Eine kleine Subroutine genügt, um nicht jeden einzelnen Errorlevelwert gesondert behandeln zu müssen.
@echo off &setlocal
REM Deine ROBOCOPY-Zeile hierher!
call :robocopycheck %errorlevel% descr
echo Is Error [0/1]: %errorlevel%
echo Description : %descr%
pause
goto :eof
:robocopycheck robocopy_errorlevel [description_variable_name]
setlocal EnableDelayedExpansion &set /a "return = %~1, err = 0" &set "txt="
if !return!==0 (set "txt=NO CHANGE ") else (
for %%i in ("COPY" "EXTRA" "MISMATCHES" "FAILS" "FATAL ERROR") do (set "bit!err!=%%~i" & set /a "err += 1")
if !return! gtr 1 (set "err=1") else set "err=0"
for /l %%i in (0 1 4) do (set /a "bit=return & 1, return >>= 1" &if !bit!==1 set "txt=!bit%%i! + !txt!")
)
endlocal &if "%~2" neq "" set "%~2=%txt:~0,-3%" &exit /b %err%
Grüße
rubberman
Hallo Viper-Berlin.
Ich weiß nicht, ob ich deine Fragen so umfangreich beantworten kann, dass es hier nicht den Rahmen sprengt, du es aber wenigstens verstehst. Ich versuch's trotzdem und beziehe mich mit der Zeilennummerierung auf deinen aufgedröselten Code.
Zeile 4
Das
Zeile 9
Zeile 15
Zeile 19
Das
In einer Kommandozeile oder einem in Klammern eingefassten Block von Kommandozeilen (zB. in einer FOR Schleife) werden normale Umgebungsvariablen nur einmal zum Wert aufgelöst, und zwar noch bevor die Zeile/der Block ausgeführt wird. Das EnableDelayedExpansion verzögert diese Auflösung, sodass die Werte zur Laufzeit der Zeile/des Blocks abgreifbar sind. Die umschließenden Prozentzeichen für die Variable sind dabei durch Ausrufezeichen zu ersetzen.
Beispiel zur Verdeutlichung:
Zeile 21
Da der Prozedur Argumente übergeben wurden, lassen sich diese auch abrufen. Das erste Argument wird durch
Zeile 41 ff
Hier wird's interessant und ich muss etwas weiter ausholen. Wenn ich oben von Bitmaske und bitweisen Operationen gesprochen habe, bedeutet das, dass hier der ROBOCOPY Rückgabewert (repräsentiert durch Variable
Nehmen wir an dass ROBOCOPY den Wert 5 als Errorlevel zurück gegeben hat, dann ergibt sich in binärer Schreibweise der Wert 00101.
Dröseln wir das mal in einer Tabelle auf:
Ich nehme an, jetzt wird das Prinzip schon mal deutlich. Wie du siehst, sind im Fall von Errorlevel 5 die Flags für MISMATCHES und COPY gesetz.
Stellt sich nur noch die Frage, wie man diese Flags in einem Batchcode vernünftig auswerten kann
Dabei helfen zwei bitweise Operationen:
1. Shift-Right (>>)
Dabei werden die einzelnen Bits eines binären Ausdrucks um die angegebene Anzahl Stellen nach rechts verschoben. Die entsprechenden niedrigsten, rechten Bits werden eliminiert, während links mit Nullen aufgefüllt wird. Bleiben wir beim Beispiel 00101 dann ergäbe >>1 die Zahl 00010, ein >>2 ergäbe 00001 usw.
2. Bitweises UND (&)
Die Regel dabei ist:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
Diese Regel wird für jedes Bit einer binären Zahl ausgeführt. Im Code verwende ich immer das
Die FOR /L Schleife sorgt dafür, dass diese Operationen 5 mal in Folge ausgeführt werden.
Für das Beispiel 00101 sieht das so aus:
Also wird jedes Bit von rechts nach links einzeln betrachtet.
Im Code oben wird einfach je nachdem, ob ein Bit gesetzt ist oder nicht, der entsprechende Text hizugefügt.
Zeile 50 ff
Falls ein zweiter Parameter übergeben wurde, so wird diesem der entsprechende Text zugewiesen (also die Beschreibung für den ROBOCOPY Errorlevelwert).
Das
So, das war viel Text und viel Information. Ich hoffe es trägt auch zum Verständnis bei
Grüße
rubberman
Ich weiß nicht, ob ich deine Fragen so umfangreich beantworten kann, dass es hier nicht den Rahmen sprengt, du es aber wenigstens verstehst. Ich versuch's trotzdem und beziehe mich mit der Zeilennummerierung auf deinen aufgedröselten Code.
Zeile 4
Das
setlocal
ist nicht unbedingt notwendig, hat sich aber eingebürgert und bewährt. Viele Scripter rufen ihre Batchdateien aus der Kommandozeile auf um sie zu debuggen. Vorteil ist, dass sich auch bei einem Syntaxfehler das Fenster nicht sofort schließt und man so erkennt, wo der Hase im Pfeffer liegt. Wenn ein Script mehrere Male aus dem gleichen CMD Fenster aufgerufen wird, so bleibt der Wert von Variablen aus dem vorangegangenen Aufruf erhalten. Das führt ggf. zu Nebenwirkungen beim erneuten Aufruf. Das setlocal
am Anfang des Codes schafft da Abhilfe. Ein endlocal
muss am Ende nicht im Code stehen, da dieses implizit bei Beendigung des Batchcodes für jedes setlocal
ausgeführt wird.Zeile 9
%errorlevel%
und descr
werden der Prozedur auf diese Weise als Argumente übergeben. Dabei enthält %errorlevel%
den Rückgabewert deines ROBOCOPY Aufrufs und descr
ist der Variablenname, dem letztlich in der Prozedur die Beschreibung, die sich aus dem Errorlevelwert ergibt, zugewiesen werden soll.Zeile 15
:robocopycheck
ist der Name der Prozedur, also das Einsprunglabel. Labelnamen werden nur bis zum ersten Leerzeichen bewertet (es gibt noch ein paar weitere Abbruchzeichen). Alles was danach kommt ist wie ein Kommentar anzusehen. Ich habe hier robocopy_errorlevel
und [description_variable_name]
hinter das Label geschrieben, um dir eine Hilfestellung zu geben, welche Argumente an die Prozedur übergeben werden müssen (ohne eckige Klammern) oder dürfen (mit eckigen Klammern).Zeile 19
Das
setlocal EnableDelayedExpansion
schaltet die verzögerte Variablenerweiterung ein.In einer Kommandozeile oder einem in Klammern eingefassten Block von Kommandozeilen (zB. in einer FOR Schleife) werden normale Umgebungsvariablen nur einmal zum Wert aufgelöst, und zwar noch bevor die Zeile/der Block ausgeführt wird. Das EnableDelayedExpansion verzögert diese Auflösung, sodass die Werte zur Laufzeit der Zeile/des Blocks abgreifbar sind. Die umschließenden Prozentzeichen für die Variable sind dabei durch Ausrufezeichen zu ersetzen.
Beispiel zur Verdeutlichung:
@echo off
setlocal
set "n=vorher"
for /l %%i in (0 1 4) do (
set "n=%%i"
echo %n%
)
endlocal
echo ~~~~~~~~~
setlocal EnableDelayedExpansion
set "n=vorher"
for /l %%i in (0 1 4) do (
set "n=%%i"
echo !n!
)
endlocal
pause
Zeile 21
Da der Prozedur Argumente übergeben wurden, lassen sich diese auch abrufen. Das erste Argument wird durch
%1
repräsentiert, das zweite durch %2
usw. Die Tilde (~) entfernt eventuell vorhandene umschließende Anführungszeichen. Letztlich erhält die Variable return
also den vorher übergebenen Rückgabewert (Errorlevel) deines ROBOCOPY Aufrufes zugewiesen.Zeile 41 ff
Hier wird's interessant und ich muss etwas weiter ausholen. Wenn ich oben von Bitmaske und bitweisen Operationen gesprochen habe, bedeutet das, dass hier der ROBOCOPY Rückgabewert (repräsentiert durch Variable
return
) als binäre Zahl betrachtet werden muss. Dieser Rückgabewert ist nämlich aus Zweierpotenzen zusammengesetzt, wobei jede dieser Zweierpotenzen einen booleschen Wert (0 für FALSCH bzw. 1 für WAHR) repräsentiert. Errorlevelwerte können eine Breite von 32 Bit haben, im Fall von ROBOCOPY reicht es aber die 5 niedrigsten Bits zu betrachten. Warum, ergibt sich aus der Tatsache, dass der schwerwiegendste Fehler den Wert 2^4 (16) hat.Nehmen wir an dass ROBOCOPY den Wert 5 als Errorlevel zurück gegeben hat, dann ergibt sich in binärer Schreibweise der Wert 00101.
Dröseln wir das mal in einer Tabelle auf:
Bit | 0 | 0 | 1 | 0 | 1 |
Wert | 2^4 (16) | 2^3 (8) | 2^2 (4) | 2^1 (2) | 2^0 (1) |
Bedeutung | FATAL ERROR | FAILS | MISMATCHES | EXTRA | COPY |
Stellt sich nur noch die Frage, wie man diese Flags in einem Batchcode vernünftig auswerten kann
Dabei helfen zwei bitweise Operationen:
1. Shift-Right (>>)
Dabei werden die einzelnen Bits eines binären Ausdrucks um die angegebene Anzahl Stellen nach rechts verschoben. Die entsprechenden niedrigsten, rechten Bits werden eliminiert, während links mit Nullen aufgefüllt wird. Bleiben wir beim Beispiel 00101 dann ergäbe >>1 die Zahl 00010, ein >>2 ergäbe 00001 usw.
2. Bitweises UND (&)
Die Regel dabei ist:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
Diese Regel wird für jedes Bit einer binären Zahl ausgeführt. Im Code verwende ich immer das
& 1
mit dem immer nur das niedrigste Bit mit 1 verglichen wird.Die FOR /L Schleife sorgt dafür, dass diese Operationen 5 mal in Folge ausgeführt werden.
Für das Beispiel 00101 sieht das so aus:
00101
& 00001
----------
00001 -> Bit ist gesetzt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00101 >>1
----------
00010
& 00001
----------
00000 -> Bit ist nicht gesetzt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00010 >>1
----------
00001
& 00001
----------
00001 -> Bit ist gesetzt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00001 >>1
----------
00000
& 00001
----------
00000 -> Bit ist nicht gesetzt
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00000 >>1
----------
00000
& 00001
----------
00000 -> Bit ist nicht gesetzt
Im Code oben wird einfach je nachdem, ob ein Bit gesetzt ist oder nicht, der entsprechende Text hizugefügt.
Zeile 50 ff
Falls ein zweiter Parameter übergeben wurde, so wird diesem der entsprechende Text zugewiesen (also die Beschreibung für den ROBOCOPY Errorlevelwert).
Das
exit /b
beendet die Prozedur, wobei ein Wert übergeben werden kann, der im Hauptcode als Errorlevel abrufbar ist.So, das war viel Text und viel Information. Ich hoffe es trägt auch zum Verständnis bei
Grüße
rubberman
Hallo Viper-Berlin.
Zunächst zu deinem Code.
Ändere Zeile 16 entweder zu
oder zu
Auch Änderungen von globalen Variablen überleben das
Hintergrund ist, dass die CMD mit
Im Fall von START wird ein neuer Prozess erzeugt. Dem wird das beim Aufruf des Befehls gültige Environment vererbt. Wenn das aus einem mit
Wenn ein Batch durch seinen Namen aus der Kommandozeile bzw. per CALL aufgerufen wird, verhält sich das etwas anders. Auch hier gilt das derzeit gültige Environment wieder genauso für den aufgerufenen Batch. Hauptunterschied ist aber, dass kein neuer Pozess erzeugt wird, sondern alles in der gleichen Instanz von cmd.exe läuft. So kommt es, dass nach Beendigung der aufgerufenen Batchdatei, Variablen auch weiterhin in der ursprünglichen Batchdatei gültig sind. Verhindern lässt sich das nur durch das
... was natürlich nur dann funktioniert, wenn der Rückgabewert numerisch und ganzzahlig ist.
Wenn man mal aus einem Block heraus die Subroutine beenden will, wäre auch so etwas mal von Interesse:
Dein Punkt 3 sollte damit auch bereits beantwortet sein.
Grüße
rubberman
Zunächst zu deinem Code.
Ändere Zeile 16 entweder zu
endlocal &set "glo_a=%glo_a%"
(
endlocal
set "glo_a=%glo_a%"
)
endlocal
sonst nicht.Hintergrund ist, dass die CMD mit
setlocal
ein eigenes Subenvironment schafft, in das vorher gesetzte Variablen zwar vererbt werden, alle in diesem Subenvironment gesetzten oder veränderten Variablenwerte aber nur dort gültig sind.1. also Setlocal macht alle Variablen in Script local was zu folge hat wenn ich einen Aufruf start irgendwas oder c:\anderescmdscript.cmd
mach das keine Variablen übergeben werden, ich kann somit die gleiche Variable mehrfach benutzen richtig.
So wie ich dich gerade verstehe, stimmt das nicht. Ein Prozess vererbt sein Environment immer an den aufgerufenen Prozess weiter.mach das keine Variablen übergeben werden, ich kann somit die gleiche Variable mehrfach benutzen richtig.
Im Fall von START wird ein neuer Prozess erzeugt. Dem wird das beim Aufruf des Befehls gültige Environment vererbt. Wenn das aus einem mit
setlocal
erzeugten Subenvironment erfolgt, werden also die dort gültigen Variablen vererbt. Der Kindprozess ändert aber nie das Environment des aufrufenden Elternprozesses.Wenn ein Batch durch seinen Namen aus der Kommandozeile bzw. per CALL aufgerufen wird, verhält sich das etwas anders. Auch hier gilt das derzeit gültige Environment wieder genauso für den aufgerufenen Batch. Hauptunterschied ist aber, dass kein neuer Pozess erzeugt wird, sondern alles in der gleichen Instanz von cmd.exe läuft. So kommt es, dass nach Beendigung der aufgerufenen Batchdatei, Variablen auch weiterhin in der ursprünglichen Batchdatei gültig sind. Verhindern lässt sich das nur durch das
setlocal
am Anfang der aufgerufenen Batchdatei.2. normalerweise atbeitet man mit lokalen Variablen in Proceduren und übergibt diese dann an global Variablen ? wie funst das in CMD
da kommt wieder nur Mist raus ????
Eine Möglichkeit habe ich oben schon gezeigt. Es gibt noch weitere. 2 Beispiele.da kommt wieder nur Mist raus ????
@echo off &setlocal
set "glob=irgendwas"
set /a "x=1, y=2"
call :proc
set /a "glob=%errorlevel%"
echo %glob%
pause
goto :eof
:proc
setlocal
set /a "loc = x + y"
(
endlocal
exit /b %loc%
)
Wenn man mal aus einem Block heraus die Subroutine beenden will, wäre auch so etwas mal von Interesse:
@echo off &setlocal
set "glob=irgendwas"
set /a "x=1, y=2"
call :proc addiere
echo %glob%
pause
goto :eof
:proc
if "%~1"=="addiere" ( REM ziemlich sinnloses IF Statement, nur zur Verdeutlichung ...
setlocal EnableDelayedExpansion
set /a "loc = x + y"
for /f "delims=" %%i in ("!loc!") do (
endlocal
set "glob=%%i"
)
)
goto :eof
Dein Punkt 3 sollte damit auch bereits beantwortet sein.
4. hat setlocal einfluss auf SETX ????
Nein. SETX ist ein Programm das Umgebungsvariablenwerte in der Registry festlegt und das Explorer-Environment aktualisiert. Das hat überhaupt nichts miteinander zu tun.Grüße
rubberman