ERRORLEVEL vs%ERRORLEVEL%vs感叹号ERRORLEVEL感叹号

时间:2017-03-23 05:21:56

标签: windows batch-file cmd 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%


)

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

1 个答案:

答案 0 :(得分:4)

错误级别

errorlevel是一个动态变量的名称(它不放在环境块中但保留在内存中),它存储上一个执行的进程/命令的退出代码(如果它设置了该值,则为{ {3}},hereherehere)。

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

但是,如果我们让批处理解析器使用变量值,%errorlevel%只是对存储在变量中的值的引用,即读操作。与!errorlevel!相同。两者之间的主要区别是 时检索值取决于变量扩展的here

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

  • 变量读取操作将检查环境块是否包含具有指示名称的变量。
  • if构造不会进行此测试。

如果您执行set errorlevel=10之类的操作,则不会使用errorlevel%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      )
  • 第1行:解析do子句中的代码,即所有代码。从代码中删除任何%var%变量读取操作,在开始执行之前用变量内的值替换。这意味着如果变量更改其值,您将无法检索更改的值,因为读操作不存在,只有变量中的初始值。

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

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

  • 第6行:当start读取操作被删除时,该行将在%errorlevel%子句开始执行之前回显存储在errorlevel变量中的值。

  • 第7行:检索do变量的当前值。在这里,我们可以遇到问题。如何命名正在执行的脚本? errorlevel.bat之间存在差异。成功时,如果这是.cmd文件,则第4行中的set命令将清除(设置为0)errorlevel变量,但如果是.cmd,则不会更改errorlevel一个.bat文件。

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

为了能够检索进程的退出代码/错误级别,我们需要等待它结束。如果你需要启动进程,如果它继续运行kill它,并且在两种情况下检索退出代码,直接调用可执行文件或使用start "" /wait programName,并行运行查杀过程(例如{{1}在启动程序之前或类似的东西)。主进程将等待并检索退出代码。监控进程处理查杀。

相关问题