ERRORLEVEL与%ERRORLEVEL%与感叹号ERRORLEVEL感叹号

cod*_*tis 4 windows cmd batch-file errorlevel

我认为我对ERRORLEVEL与%ERRORLEVEL%有基本的了解,但是!ERRORLEVEL!使我困惑。

我正在制作一个脚本,该脚本调用可执行文件,然后任务列表以查看其是否正在运行,然后通过taskkill将其杀死,然后尝试输出错误级别并针对其他exe重复此操作,而我意识到我真的不明白批处理中的错误级别。

我将变量设置为!errorlevel!然后在回显中使用不带引号的变量,并且在设置后出现错误时,变量从一个uint16更改为另一个uint16,例如它引用了真实的变量而不是副本。我要复制。有人可以解释这些家伙之间的区别吗?


更新:这是我正在处理的代码段。

for %%P in (%executableList%) do (
   echo ----------------------------------------------------------------------------------       
    set exeErrorlevel=0
    set running=false

    start %%~fP  
    set exeErrorlevel=!ERRORLEVEL!

    rem for debugging purposes
    echo %%~nP%%~xP older errorlevel %ERRORLEVEL%       
    echo %%~nP%%~xP newer errorlevel !ERRORLEVEL!        
    echo before tasklist running var is : !running!

    tasklist /FI "IMAGENAME eq %%~fP" | find /I /N /C  "%%~fP" >nul && set running=true

    echo after tasklist is running var is: !running!

    if !running! equ true ( 
       echo %%~nP%%~xP Program is running
       taskkill /F /IM %%~nP%%~xP /T
       echo %%~nP%%~xP Program was killed          

       if !exeErrorlevel! == 0 (
           echo %passString% %%~nP%%~xP process was started and killed safely 
           echo %passString% %%~nP%%~xP process was started and killed safely >>%outputfile%
       ) else ( 
           echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel!
           echo %failString% %%~nP%%~xP process was killed with errorcode !exeErrorlevel! >>%outputfile%                  
       )         
    ) else (             
         if !exeErrorlevel! == 0 (
             echo %passString% %%~nP%%~xP process exited safely
             echo %passString% %%~nP%%~xP process exited safely >>%outputfile%
         ) else (                 
             taskkill /F /IM %%~nP%%~xP /T
             echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel! 
             echo %failString% %%~nP%%~xP process abruptly exited with errorcode !exeErrorlevel! >>%outputfile%                  
         )                    
    )

    echo. >>%outputfile%


)
Run Code Online (Sandbox Code Playgroud)

我需要确保exeErrorlevel在某个时间点具有错误级别的副本-我只想从exe捕获错误,而不是从tasklist / find / taskill的成功/失败捕获错误。我担心由于扩展延迟,exeerrorlevel在执行时会访问延迟的错误级别。也许应该将其设置为exeErrorlevel =%errorlevel%。在我回显旧变量和新变量的行中通常返回不同的整数吗?在我所有的测试运行中,%errorlevel%似乎通常返回0,而!errorlevel!则返回0。对于具有错误退出代码的可执行文件,始终为非零。

MC *_* ND 6

错误级别

errorlevel是动态变量的名称(不是放置在环境块中,而是保存在内存中),用于存储先前执行的过程/命令的退出代码(如果设置了该值,请在此处此处此处此处阅读)。

if命令允许使用if errorlevel n语法来检查errorlevel变量的值是否大于或等于n,而无需批处理解析器检索变量的值。

但是,如果我们将批处理解析器与变量值一起使用,%errorlevel%则仅是对存储在变量中的值的引用,即读取操作。与相同!errorlevel!。两者之间的主要区别是,当该值是根据所检索的规则上变量扩展。

使用if errorlevel或检索变量中的值有很大的不同:

  • 变量读取操作将检查环境块是否包含具有指定名称的变量。
  • ifconstuct不会让这个测试。

如果执行类似的操作set errorlevel=10errorlevel将不会使用%errorlevel%或来检索动态值,!errorlevel!因为在环境中设置的值将隐藏动态值。但是,由于if errorlevel不读取环境块而是直接读取保存该值的内部变量,因此它将正常工作。

变量

批处理语法不包括以下选项:在内存中具有多个指向同一值的变量,如果其中一个变量更改了其值,则另一个变量将反映该更改。

可以通过在变量扩展中正确使用不同阶段,将变量正确设置为另一个变量的名称并强制批处理解析器对该命令进行两次传递来模拟此行为,以便将第一个变量解析为第二个变量的名称。真正的价值。

你的问题

简化(甚至无法正常工作)的代码仅用于分析

 1  for %%P in (%executableList%) do (
 2  
 3      start %%~fP  
 4      set exeErrorlevel=!ERRORLEVEL!
 5  
 6      echo %%~nP%%~xP older errorlevel %ERRORLEVEL%       
 7      echo %%~nP%%~xP newer errorlevel !ERRORLEVEL!        
 8      ....
 9      if !running! equ true ( 
10         taskkill /F /IM %%~nP%%~xP /T
11         if !exeErrorlevel! == 0 (
12          ....
13         ) else ( 
14             echo process killed with errorcode !exeErrorlevel!
15         )         
16      ) else (             
17           if !exeErrorlevel! == 0 (
18             ....
19           ) else (                 
20               taskkill /F /IM %%~nP%%~xP /T
21               echo process abruptly exited with errorcode !exeErrorlevel! 
22           )                    
23      )
Run Code Online (Sandbox Code Playgroud)
  • 第1行:do子句中的代码,所有代码均被解析。%var%在开始执行之前,将从代码中删除所有变量读取操作,并替换为变量内部的值。这意味着,如果变量更改了其值,则将无法检索更改的值,因为不存在读取操作,只能获取变量中的初始值。

  • 第3行:可执行文件是在单独的进程中启动的,无需等待进程结束。那很重要么?见下一行

  • 第4行:errorlevel检索变量的当前值(使用延迟扩展)并将其存储在exeErrorlevel变量中。但是存储的值不是errorlevel可执行文件返回的值(单独的进程,不等待其结束,我们怎么知道是什么exit code = errorlevel?),而是start命令的退出代码。

  • 第6行:由于%errorlevel%删除了读取操作,此行将回显在子句开始执行errorlevel之前存储在变量中的值do

  • 第7行:errorlevel检索变量的当前值。在这里,我们可能会遇到问题。如何执行脚本的命名?.bat和之间有区别.cmd。上sucess的set第4行命令将清除(设置为0)的errorlevel变量,如果这是一个.cmd文件,但将不改变errorlevel,如果它是一个.bat文件。

  • 第11、14、21行:如所示,该exeErrorlevel变量不包含有效值。不,将行更改为!errorlevel!不会检索流程的退出代码,而是的退出代码taskkill

为了能够检索进程的退出代码/错误级别,我们需要等待它结束。如果您需要启动该进程,如果它保持运行状态,则将其杀死,然后在两种情况下都检索退出代码,请直接调用该可执行文件或使用start "" /wait programName,并并行运行该杀死进程(例如,start /b "" monitor.bat programName在启动程序之前,执行类似操作)。主进程将等待并检索退出代码。监视进程处理杀死事件。


归档时间:

查看次数:

3214 次

最近记录:

8 年,9 月 前