簡體   English   中英

如何通過引用另一個批處理文件將環境變量作為參數傳遞?

[英]How to pass environment variables as parameters by reference to another batch file?

我對 Windows 批次有疑問。 我有兩個批處理文件/腳本,第一個調用第二個,多次使用不同的參數。

我想在第一個中創建幾個環境變量並將它們作為參數傳遞給第二個。 在第二個批處理腳本中,傳遞的變量應分別增加一個在第二個批處理文件中確定的值。 然后在第二個批處理文件的下一次調用中再次傳遞第一個批處理文件中的環境變量,並且它們的值應該由第二個批處理文件相應地再次遞增。

First.bat 腳本:

::Modules find
set anz_Modules=0
::Modules build successful
set SR_Modules=0
set CPP_Modules=0

call ./Pearl_p2cpp.bat EXTRA auto anz_Modules SR_Modules CPP_Modules
rem Here are more calls of Pearl_p2cpp.bat with varying first parameter.
call ./Pearl_p2cpp.bat FKT auto anz_Modules SR_Modules CPP_Modules

Second.bat 腳本Pearl_p2cpp.bat

::Globale Variablen aus *_ALLES.bat bearbeiten
if NOT[%3]==[] goto noParams
set /a "%~3=%3%+%numberOfModuls%"

if NOT[%4]==[] goto noParams
set /a "%~4=%4%+%SRecordSuccess%"

if NOT[%5]==[] goto noParams
set /a "%~5=%5%+%CppSuccess%"

:noParams

再次使用 First.bat 腳本:

echo Es wurden insgesammt [%anz_Modules%]*.P (PEARL)-Module gefunden
echo aus diesen wurden [%SR_Modules%]-SREC und [%CPP_Modules%]-C++ Dateien in %TookTime:~0,-2%.%TookTime:~-2% seconds gebuildet! 

Output:

Es wurden insgesammt [0]*.P (PEARL)-Module gefunden
aus diesen wurden [0]-SREC und [0]-C++ Dateien in 143.41 seconds gebuildet!

增加或編輯變量似乎不起作用。

問題是什么?

2021 年 4 月 9 日更新:

以下是根據 Mofi 在最終刪除的評論中的建議更改的批處理腳本 第二個批處理文件現在使用保存臨時值的局部變量。 第二個批處理文件應在endlocal末尾使用 set "%~3=%interimVAR%"傳回新值。

但是 output 仍然是錯誤的,因為 output 是第一個批處理文件的初始值。

完整的 first.bat 腳本:

@echo off

:: Store start time
set StartTIME=%TIME%
set H=%StartTIME:~0,2%
if "%H:~0,1%"==" " set H=%H:~1,1%
if "%H:~0,1%"=="0" set H=%H:~1,1%
set M=%StartTIME:~3,2%
if "%M:~0,1%"=="0" set M=%M:~1,1%
set S=%StartTIME:~6,2%
if "%S:~0,1%"=="0" set S=%S:~1,1%
set U=%StartTIME:~9,2%
if "%U:~0,1%"=="0" set U=%U:~1,1%
)
set /a Start100S=%H%*360000+%M%*6000+%S%*100+%U%

::Modules found
set /A "anz_Modules = 0"
::Modules build successful
set /A "SR_Modules = 0"
set /A "CPP_Modules = 0"

call "%~dp0Pearl_p2cpp.bat" EXTRA auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" FKT auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" FKTREP auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" FKTZU auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" KALIB auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" LASER auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" MOAB auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" MOENDE auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" MOZU auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" MTERM auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" MTERM\RTOS auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ..
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" PAKZU auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" PE auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" SRS auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" SRTBEG2 auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" STDBY auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" VDE auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

call "%~dp0Pearl_p2cpp.bat" VGL auto %anz_Modules% %SR_Modules% %CPP_Modules%
call cd ../.batch_scripts

:: Get the end time
set StopTIME=%TIME%
set H=%StopTIME:~0,2%
if "%H:~0,1%"==" " set H=%H:~1,1%
if "%H:~0,1%"=="0" set H=%H:~1,1%
set M=%StopTIME:~3,2%
if "%M:~0,1%"=="0" set M=%M:~1,1%
set S=%StopTIME:~6,2%
if "%S:~0,1%"=="0" set S=%S:~1,1%
set U=%StopTIME:~9,2%
if "%U:~0,1%"=="0" set U=%U:~1,1%
)

set /a Stop100S=%H%*360000+%M%*6000+%S%*100+%U%
:: Test midnight rollover. If so, add 1 day=8640000 1/100ths secs
if %Stop100S% LSS %Start100S% set /a Stop100S+=8640000
set /a TookTime=%Stop100S%-%Start100S%
echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo ----------------------------------------------------------------------------------------------------
::echo um %StartTime% Uhr gestartet
::echo um %StopTime% Uhr beendet
echo Es wurden insgesammt [%anz_Modules%]*.P (PEARL)-Module gefunden
echo aus diesen wurden [%SR_Modules%]-SREC und [%CPP_Modules%]-C++ Dateien in %TookTime:~0,-2%.%TookTime:~-2% seconds gebuildet! 
echo ----------------------------------------------------------------------------------------------------
echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

完整的 second.bat 腳本完整:

@echo off    

echo compile and port moduls in subfolder "%1"
cd .././%1
pwd
echo *.Px ,*.cpp und *.SR-Dateien werden geloescht.

if /i "%2%"=="auto" GOTO nopause_1

pause

rm *.Px
rm *.SR

echo Konvertierungen starten:

:nopause_1

if /i "%2%"=="auto" GOTO no_time_rec

  :: Store start time
  set StartTIME=%TIME%
  set H=%StartTIME:~0,2%
  if "%H:~0,1%"==" " set H=%H:~1,1%
  if "%H:~0,1%"=="0" set H=%H:~1,1%
  set M=%StartTIME:~3,2%
  if "%M:~0,1%"=="0" set M=%M:~1,1%
  set S=%StartTIME:~6,2%
  if "%S:~0,1%"=="0" set S=%S:~1,1%
  set U=%StartTIME:~9,2%
  if "%U:~0,1%"=="0" set U=%U:~1,1%
  )
  set /a Start100S=%H%*360000+%M%*6000+%S%*100+%U%

:no_time_rec

setlocal EnableDelayedExpansion

set cppExtension=".cpp"
set PearlExtension=".P"
set SRecordExtension=".SR"

set /a "SRecordSuccess=0"
set /a "CppSuccess=0"
set /a "numberOfModuls=0"
set doCompilePort=true

for /f %%a IN ('dir /b *.P') do (
  
  echo Modul %%a
  set doCompilePort=true

  if "%%a" == "INCL.P" set doCompilePort=false
  if "%%a" == "INCL_FKR.P" set doCompilePort=false
  if "%%a" == "INCL_GLO.P" set doCompilePort=false
  if "%%a" == "INCL_PE.P" set doCompilePort=false
  if "%%a" == "INCL_STB.P" set doCompilePort=false
  if "%%a" == "INCL_VDE.P" set doCompilePort=false
  
  echo doCompilePort:!doCompilePort!
  
  
  if "!doCompilePort!" == "true" (
    echo start compiler
    

    set /a numberOfModuls=!numberOfModuls!+1
    echo modul number !numberOfModuls!
    
    echo Convert
    set filename=%%a
    set fileBasename=!filename:~0,-2!
    rm !fileBasename!.cpp
    echo returnValue rm !errorlevel!
  
    set filenameSR=!fileBasename!.SR

    call C:\programme\compiler\rtos-uh\pe\pe.exe C:\programme\compiler\rtos-uh\ppc\PEARL90\vers16_6\P16Q6H.VBI -si=!filename! -co=!filenameSR! -lo=no -e0
    IF !errorlevel! NEQ 0 (
      REM do something here to address the error
      echo returnValue Pearl-Compiler !errorlevel!
    ) ELSE (
      set /a SRecordSuccess=!SRecordSuccess!+1
    )
        

    call pqprep !filename!
    echo returnValue pqprep !errorlevel!
    
    call p2cpp !filename!x
    
    IF !errorlevel! NEQ 0 (
      REM do something here to address the error
      echo returnValue Pearl-Compiler !errorlevel!
    ) ELSE (
      set /a CppSuccess=!CppSuccess!+1
    )
  )
  echo ----------------------------------------------------------------------------------------------------
)
echo ----------------------------------------------------------------------------------------------------

echo number of moduls: %numberOfModuls%
echo successfully created S-Records: %SRecordSuccess%
echo successfully created cpp-files: %CppSuccess%

IF %numberOfModuls% == %SRecordSuccess% (
  IF %numberOfModuls% == %CppSuccess% (
    echo all moduls successful
  )
)

::Globale Variablen aus *_ALLES.bat bearbeiten
if "%~3" == "" goto noParams
set /A "PassedVar3=%~3+numberOfModuls"

if "%~4" == "" goto noParams
set /A "PassedVar4=%~4+SRecordSuccess"

if "%~5" == "" goto noParams
set /A "PassedVar5=%~5+CppSuccess"

:noParams

if /i "%2%"=="auto" GOTO no_time_rec2

  :: Get the end time
  set StopTIME=%TIME%
  set H=%StopTIME:~0,2%
  if "%H:~0,1%"==" " set H=%H:~1,1%
  if "%H:~0,1%"=="0" set H=%H:~1,1%
  set M=%StopTIME:~3,2%
  if "%M:~0,1%"=="0" set M=%M:~1,1%
  set S=%StopTIME:~6,2%
  if "%S:~0,1%"=="0" set S=%S:~1,1%
  set U=%StopTIME:~9,2%
  if "%U:~0,1%"=="0" set U=%U:~1,1%
  )

  set /a Stop100S=%H%*360000+%M%*6000+%S%*100+%U%
  :: Test midnight rollover. If so, add 1 day=8640000 1/100ths secs
  if %Stop100S% LSS %Start100S% set /a Stop100S+=8640000
  set /a TookTime=%Stop100S%-%Start100S%

  echo wurden in %TookTime:~0,-2%.%TookTime:~-2% seconds uebersetzt und in PEARL-SRs compiliert
  echo ----------------------------------------------------------------------------------------------------

:no_time_rec2

echo *.Px -Dateien werden geloescht.
echo ----------------------------------------------------------------------------------------------------

if /i "%2%"=="auto" GOTO nopause_2

Pause

:nopause_2

rm *.Px
rm *.phx
rm *.INCx

rm *.incx


pwd
cd ./..
pwd

if "%~3" == "" goto noParams
endlocal & set "%~3=%PassedVar3%" "%~4=%PassedVar4%" "%~5=%PassedVar5%"

:noParams

echo Vorgang beenden

這是重寫的完整的第一個批處理文件:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Get start time region independent in seconds and hundredths of a second
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalTime=%%I"
set /A Start100S=(1%LocalTime:~8,2%-100)*360000 + (1%LocalTime:~10,2%-100)*6000 + (1%LocalTime:~12,2%-100)*100 + (1%LocalTime:~15,2%-100)

rem Modules found
set "anz_Modules=0"
rem Modules build successful
set "SR_Modules=0"
set "CPP_Modules=0"

call "%~dp0Pearl_p2cpp.bat" EXTRA      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" FKT        auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" FKTREP     auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" FKTZU      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" KALIB      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" LASER      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" MOAB       auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" MOENDE     auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" MOZU       auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" MTERM      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" MTERM\RTOS auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" PAKZU      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" PE         auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" SRS        auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" SRTBEG2    auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" STDBY      auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" VDE        auto anz_Modules SR_Modules CPP_Modules
call "%~dp0Pearl_p2cpp.bat" VGL        auto anz_Modules SR_Modules CPP_Modules

rem Get end time region independent in seconds and hundredths of a second
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalTime=%%I"
set /A Stop100S=(1%LocalTime:~8,2%-100)*360000 + (1%LocalTime:~10,2%-100)*6000 + (1%LocalTime:~12,2%-100)*100 + (1%LocalTime:~15,2%-100)

rem Test midnight rollover. If so, add one day=8640000 1/100ths seconds
if %Stop100S% LSS %Start100S% set /A Stop100S+=8640000
set /A TookTime=Stop100S - Start100S
echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo ----------------------------------------------------------------------------------------------------
echo Es wurden insgesammt [%anz_Modules%]*.P (PEARL)-Module gefunden.
echo Aus diesen wurden [%SR_Modules%]-SREC und [%CPP_Modules%]-C++ Dateien in %TookTime:~0,-2%.%TookTime:~-2% Sekunden erzeugt!
echo ----------------------------------------------------------------------------------------------------
echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
endlocal

這個批處理文件首先用前兩個命令行完全定義了執行環境:

  • 命令回顯模式已關閉。
  • 命令擴展已啟用。
  • 延遲變量擴展被禁用。

命令SETLOCAL

  • 將命令擴展的當前狀態推送到堆棧上,
  • 將延遲擴展的當前狀態推送到堆棧上,
  • 將當前目錄的完整路徑推送到堆棧上,
  • 將指針推送到堆棧上的當前環境變量列表,
  • 創建當前環境變量列表的副本並將該副本用作活動環境變量列表。

這總是由命令SETLOCAL完成,獨立於在沒有、一個或兩個參數的情況下運行。

命令ENDLOCAL

  • 丟棄當前的環境變量列表,
  • 從堆棧中彈出指向前一個環境變量列表的指針,並使這個環境變量列表再次成為活動環境變量列表,
  • 從堆棧中彈出前一個當前目錄的完整路徑,如果該目錄仍然存在,則將該目錄設為當前目錄,
  • 從堆棧中彈出延遲擴展的先前狀態並相應地設置延遲擴展的狀態,
  • 從堆棧中彈出命令擴展的先前狀態並相應地設置命令擴展的狀態。

這也由 Windows 命令處理器cmd.exe為在批處理文件中執行的每個SETLOCAL隱式完成,在退出批處理文件的處理之前未明確執行ENDLOCAL 因此,許多在頂部某處使用SETLOCAL的批處理文件在最后某處不包含ENDLOCAL

也可以看看:

因此批處理文件在其自己的本地執行環境中運行,該環境不依賴於批處理文件之外定義的內容,當前目錄除外,因為從該批處理文件傳遞到被調用批處理文件Pearl_p2cpp.bat的所有目錄路徑都是相對於在批處理文件之外定義的當前目錄。 這可能不是那么好,但我不能評價。

可以使用第三個命令行pushd "%~dp0"將當前目錄路徑推送到堆棧上,並使批處理文件的目錄成為當前目錄,並作為最后一行popd從堆棧中彈出目錄路徑的初始當前目錄,並再次將此目錄設置為當前目錄。

接下來的兩個命令行獲取當前本地時間,獨立於百分之一秒的地區/國家,並計算開始時間的值。 有關解釋,請參閱午夜后的時間設置不正確

在算術表達式中,時間的每個兩位十進制數前面都有字符1 ,導致所有數字現在都是三位數字,最小值為100 這是因為SET將算術表達式中以0開頭的數字解釋為八進制數而不是十進制數。 數字89在八進制數中無效。 因此, 0809將被解釋為無效的八進制數,而不是十進制數89 避免將十進制數解釋為八進制數的簡單解決方案是在算術表達式字符串中的每個兩位十進制數之前插入字符1 ,並在計算算術表達式時從每個十進制數中減去100

使用時間格式hh:mm::ss.xx獲取開始/結束時間區域/國家/地區的更好代碼是:

rem Get start time region dependent in seconds and hundredths of a second.
set "LocalTime=%TIME%"
set "Hour=%LocalTime:~0,2%"
if "%Hour:~0,1%" == "0" (set "Hour=%Hour:~1%") else if "%Hour:~0,1%" == " " set "Hour=%Hour:~1%"
set "Minute=%LocalTime:~3,2%
if "%Minute:~0,1%" == "0" set "Minute=%Minute:~1%"
set "Second=%LocalTime:~6,2%"
if "%Second:~0,1%" == "0" set "Second=%Second:~1%"
set "HundredthOfSecond=%LocalTime:~9,2%
if "%HundredthOfSecond:~0,1%" == "0" set "HundredthOfSecond=%HundredthOfSecond:~1%"
set /A Start100S=Hour*360000 + Minute*6000 + Second*100 + HundredthOfSecond

rem Or for the end time the lines above with last line modified to:
set /A Stop100S=Hour*360000 + Minute*6000 + Second*100 + HundredthOfSecond

這里通過額外的IF條件避免了八進制數問題,這些條件重新定義了字符串值的第一個字符為0 (或小時值上的空格)的適當環境變量,只有第二個字符。 所以算術表達式中沒有數字有前導0

請永遠不要在算術表達式中引用環境變量,即使用%! set /A之后的字符串。 . 這是不必要的,而且適得其反。 環境變量可以在算術表達式中僅通過它們的名稱來引用,以便更容易使用它們,尤其是在IF條件塊或FOR循環中。 有一些例外情況,例如環境變量名稱包含空格或字符,在算術表達式中被解釋為數學運算符,或者在算術表達式中應僅使用環境變量的字符串值的一部分。 但一般來說,只有變量名可以在算術表達式中使用,才能使用良好的環境變量名。

接下來的命令行定義了三個值為 0 的環境變量。一般不應使用算術表達式來定義具有數字的環境變量。 環境變量始終是 memory 中的字符串,而不是 integer。 因此,與使用set "anz_Modules=0" "anz_Modules=0" 的簡單字符串定義相比,使用諸如set /A "anz_Modules = 0"類的算術表達式定義環境變量需要更多的 CPU 指令,盡管沒有用戶注意到差異,因為 CPU 非常如今快。 另請參閱:在命令行上使用 'set var = text' 后,為什么沒有字符串 output 和 'echo %var%'?

下一個命令行塊是對具有完全限定文件名的批處理文件Pearl_p2cpp.bat的簡單調用。 此批處理文件始終存儲在與第一個批處理文件相同的目錄中,因此使用%~dp0擴展為第一個批處理文件的完整路徑始終以反斜杠結尾確保(幾乎總是)第二個批處理文件確實調用獨立於哪個目錄是當前目錄。

帶有命令CD的命令行全部被刪除,因為它們不再需要在批處理文件Pearl_p2cpp.bat中使用PUSHDPOPD

注意:CD一樣在cmd.exe的內部命令上使用命令CALL是危險的,至少會增加批處理文件的執行時間。 Windows 命令處理器在CALL之后期望以冒號開頭的參數字符串被解釋為當前批處理文件中的 label 應該像子例程一樣調用,即批處理文件中的批處理文件,或者批處理文件的名稱沒有或帶路徑,不帶或帶文件擴展名。 因此, call cd結果在cmd.exe中搜索當前目錄,然后在環境變量PATH的值中的所有目錄中搜索文件名為cd (不區分大小寫)且文件擴展名列在環境變量PATHEXT值中的文件以及何時它確實找到了這樣一個文件,這個文件是通過將內部命令CD的 arguments 傳遞給這個可執行文件或腳本來執行的,而不是運行內部命令來更改當前目錄。

接下來確定停止/結束時間,並在批處理文件執行結束時計算最終信息 output 的時間差。

這是完整的第二個批處理文件Pearl_p2cpp.bat重寫,但未經過全面測試:

@echo off
echo Kompiliere und portiere Module im Unterverzeichnis: "%~1"
pushd "..\%~1" || exit /B
echo "%CD%"
echo *.Px und *.SR Dateien werden entfernt.

if /I not "%~2" == "auto" pause

if exist *.Px del /Q *.Px
if exist *.SR del /Q *.SR

if /I "%~2" == "auto" GOTO no_time_rec

rem Get start time region independent in seconds and hundredths of a second
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalTime=%%I"
set /A Start100S=(1%LocalTime:~8,2%-100)*360000 + (1%LocalTime:~10,2%-100)*6000 + (1%LocalTime:~12,2%-100)*100 + (1%LocalTime:~15,2%-100)

:no_time_rec

setlocal EnableExtensions EnableDelayedExpansion
echo Konvertierungen starten:
set "SRecordSuccess=0"
set "CppSuccess=0"
set "numberOfModules=0"

for /F "eol=| delims=" %%I in ('dir /A-D /B *.P 2^>nul') do (

    echo Modul %%I
    set "doCompilePort=true"

    if /I "%%I" == "INCL.P"     set "doCompilePort="
    if /I "%%I" == "INCL_FKR.P" set "doCompilePort="
    if /I "%%I" == "INCL_GLO.P" set "doCompilePort="
    if /I "%%I" == "INCL_PE.P"  set "doCompilePort="
    if /I "%%I" == "INCL_STB.P" set "doCompilePort="
    if /I "%%I" == "INCL_VDE.P" set "doCompilePort="

    if defined doCompilePort (
        echo doCompilePort:true
        echo start compiler

        set /A numberOfModules+=1
        echo module number !numberOfModules!

        echo Convert
        if exist "%%~nI.cpp" del /F "%%~nI.cpp"
        echo returnValue del !errorlevel!

        "C:\programme\compiler\rtos-uh\pe\pe.exe" "C:\programme\compiler\rtos-uh\ppc\PEARL90\vers16_6\P16Q6H.VBI" -si="%%I" -co="%%~nI.SR" -lo=no -e0
        if errorlevel 1 (
            rem Do something here to address the error.
            echo returnValue Pearl Compiler !errorlevel!
        ) else set /A SRecordSuccess+=1

        call pqprep %%I
        echo returnValue pqprep !errorlevel!

        call p2cpp %%Ix
        if errorlevel 1 (
            rem Do something here to address the error.
            echo returnValue p2cpp !errorlevel!
        ) else set /A CppSuccess+=1
    ) else echo doCompilePort:false

    echo ----------------------------------------------------------------------------------------------------
)
echo ----------------------------------------------------------------------------------------------------

echo number of modules: %numberOfModules%
echo successfully created S-Records: %SRecordSuccess%
echo successfully created cpp-files: %CppSuccess%

if %numberOfModules% == %SRecordSuccess% if %numberOfModules% == %CppSuccess% echo all modules successful

rem Globale Variablen aus *_ALLES.bat addieren.
if "%~3" == "" goto noParams
if "%~4" == "" goto noParams
if "%~5" == "" goto noParams

set /A numberOfModules+=%~3
set /A SRecordSuccess+=%~4
set /A CppSuccess+=%~5

:noParams
if /I "%~2" == "auto" goto no_time_rec2

rem Get end time region independent in seconds and hundredths of a second
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalTime=%%I"
set /A Stop100S=(1%LocalTime:~8,2%-100)*360000 + (1%LocalTime:~10,2%-100)*6000 + (1%LocalTime:~12,2%-100)*100 + (1%LocalTime:~15,2%-100)

rem Test midnight rollover. If so, add 1 day=8640000 1/100ths seconds
if %Stop100S% LSS %Start100S% set /A Stop100S+=8640000
set /A TookTime=Stop100S - Start100S

echo Die Dateien wurden in %TookTime:~0,-2%.%TookTime:~-2% Sekunden verarbeitet und in PEARL-SRs kompiliert.
echo ----------------------------------------------------------------------------------------------------

:no_time_rec2
echo *.Px Dateien werden entfernt.
echo ----------------------------------------------------------------------------------------------------
if /I not "%~2" == "auto" pause
if exist *.Px   del /Q *.Px
if exist *.phx  del /Q *.phx
if exist *.INCx del /Q *.INCx
if exist *.incx del /Q *.incx

if not "%~3" == "" (endlocal & set "%~3=%numberOfModules%" & set "%~4=%SRecordSuccess%" & set "%~5=%CppSuccess%") else endlocal
echo Vorgang beenden
popd

該批處理文件首先將當前目錄的完整路徑推送到堆棧上,並根據傳遞的第一個參數字符串使該目錄與當前目錄的相對路徑成為新的當前目錄。 批處理文件期望第一個傳遞的目錄是當前目錄的父目錄的子目錄。

請閱讀有關命名文件、路徑和命名空間的 Microsoft 文檔,了解將.././替換為..\的說明。 Windows 上的目錄分隔符是反斜杠\而不是 Linux/Mac 上的斜杠/ Windows 的大多數文件/文件夾參數字符串也可以與/一起使用,因為 Windows 文件管理在將文件/文件夾名稱字符串傳遞給文件系統之前將所有/替換為\ 但我知道在文件/文件夾名稱字符串中使用/會導致意外行為的幾個用例。 ..\ (父目錄)之后的.\ (當前目錄)總是無用的。 只要有父目錄,父目錄的當前目錄就是已經用..\引用的父目錄。

文件/文件夾字符串應始終包含在"中,以確保使用它們的命令即使在包含空格或這些字符之一&()[]{}^=;,'+,`~也能正常工作。

命令pwd (打印工作目錄)是 Linux 命令。 Windows 上的一種替代方法是echo "%CD%"或 not safe echo %CD% 如果當前目錄路徑包含一個或多個& ,則后者的作用與僅輸出當前目錄路徑不同。 所以最好用雙引號將當前目錄路徑括起來,參見上面的段落。 沒有"的安全替代方法是setlocal EnableDelayedExpansion & echo !CD!& endlocal 。但是在這種情況下,在 output 的當前目錄路徑中做了很多工作,沒有雙引號。

命令rm (刪除)也是一個 Linux 命令。 Windows 命令對於文件是del (刪除),對於目錄是rd (刪除目錄)。

改進后的第二個批處理文件仍然包含命令SETLOCAL以啟用延遲擴展 但這僅適用於for循環中的某些echo命令行。 真正需要的命令行不再需要延遲的環境變量擴展。 除了一些echo命令行之外,所有其他命令行都使用推薦的語法,這使得延遲擴展的使用變得不必要。

我無法測試FOR循環內的任何內容,因此只能希望第二個批處理文件的這一部分按您的預期工作。

在批處理文件頂部設置的當前目錄中傳遞給pqprepp2cpp的兩個文件名(批處理文件,可執行文件?)沒有包含在"因為它應該這樣做,因為我不知道這兩個腳本或可執行文件支持用雙引號括起來的文件名。兩個重寫的批處理文件現在這樣做了,除了帶有pqprepp2cpp的兩個命令行與兩個原始批處理文件相比,這兩個原始批處理文件對於具有一個或多個的目錄或文件名會失敗多次空格或&()^=;,'+,在文件/目錄名稱中。好吧,由於啟用了延遲擴展,由FOR循環處理的 *.P 文件名稱中的感嘆號仍然是一個問題。

必須將要由第二個批處理文件修改的環境變量的名稱傳遞給第二個批處理文件,而不是它們的當前值,否則第二個批處理文件將不知道要在第一個批處理文件的環境變量列表中重新定義哪些環境變量批處理文件。

我不明白為什么要刪除*.INCx*.incx文件,因為 Windows 文件系統不區分大小寫。 但是當前目錄可能是網絡驅動器,網絡資源上的文件系統是 Linux 文件系統,區分大小寫。

最重要的是最后一個IF條件命令行:

if not "%~3" == "" (endlocal & set "%~3=%numberOfModules%" & set "%~4=%SRecordSuccess%" & set "%~5=%CppSuccess%") else endlocal

環境變量numberOfModulesSRecordSuccessCppSuccess是第二個批處理文件的本地環境變量。 通過環境變量anz_ModulesSR_ModulesCPP_Modules的值,它們的值在上面的幾行中增加了,它們的名稱被傳遞到第二個批處理文件。

現在需要顯式運行ENDLOCAL以在退出處理第二個批處理文件之前恢復第一個批處理文件的環境變量列表,並在調用批處理文件的環境變量列表中另外重新定義環境變量anz_ModulesSR_ModulesCPP_Modules 這是通過在同一命令塊中的同一行上分別使用以(和結尾)三倍的命令SET來完成的,其中環境變量名稱作為 arguments 和三個本地環境變量的當前值傳遞給批處理文件。

Windows 命令處理器CMD首先使用IF條件處理整個命令行,如Windows 命令解釋器 (CMD.EXE) 如何解析腳本中詳細描述的那樣? 在命令行處理期間, %~3anz_Modules%numberOfModules%"替換為本地環境變量numberOfModules的當前值。同樣對%~4%SRecordSuccess%%~5%CppSuccess% . 最終執行的IF命令行不再包含參數或環境變量引用。整個命令行僅包含所有引用的字符串。因此,調用批處理文件的三個環境變量重新定義為三個值在IF條件的真或假分支中執行命令ENDLOCAL后不再存在的局部環境變量。

最后一個IF條件也可以寫成:

if not "%~3" == "" (
    endlocal
    set "%~3=%numberOfModules%"
    set "%~4=%SRecordSuccess%"
    set "%~5=%CppSuccess%"
) else endlocal

結果將與 Windows 命令處理器解析整個塊並在執行命令IF之前將所有參數和環境變量引用替換為其字符串值相同。

最后,第二個批處理文件恢復了初始當前目錄,這使得第一個批處理文件中的命令CD的使用變得不必要。

要了解使用的命令及其工作原理,請打開命令提示符window,在其中執行以下命令,並仔細閱讀每個命令顯示的所有幫助頁面。

  • call /?
  • cmd /?
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • popd /?
  • pushd /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic os /?
  • wmic os get /?

有關運算符&||的說明,另請參見使用 Windows 批處理文件的單行多命令 .

閱讀有關使用命令重定向運算符的 Microsoft 文檔,了解2>nul的說明。 當 Windows 命令解釋器在執行命令FOR執行嵌入式dir命令行之前使用在后台啟動的單獨命令進程來執行嵌入式 dir 命令行時,重定向運算符>必須在FOR命令行上使用脫字符^進行轉義,以將其解釋為文字字符%ComSpec% /c'中的命令行作為附加的 arguments 附加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM