ERRORLEVEL与%ERRORLEVEL%与感叹号ERRORLEVEL感叹号 [英] ERRORLEVEL vs %ERRORLEVEL% vs exclamation mark ERRORLEVEL exclamation mark

查看:124
本文介绍了ERRORLEVEL与%ERRORLEVEL%与感叹号ERRORLEVEL感叹号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我对ERRORLEVEL和%ERRORLEVEL%有基本的了解,但是!ERRORLEVEL!使我感到困惑.

I think i have a basic understanding of ERRORLEVEL vs %ERRORLEVEL% but !ERRORLEVEL! confuses me.

我正在制作一个脚本,该脚本调用可执行文件,然后任务列表以查看其是否正在运行,然后通过taskkill将其杀死,然后尝试输出错误级别并针对其他exe重复执行此操作,我意识到我确实不知道该怎么做.无法批量了解错误级别.

I'm making a script that calls an executable, then tasklist to see if its running, then taskkill to kill it if it is and then trying to output the errorlevels and repeating for other exe's and i'm realising i really don't understand errorlevels in batch.

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

I set a variable equal to !errorlevel! then used that variable without quotation marks in an echo, and the variable changed from one uint16 to another uint16 when there was an error after the set, like its a reference to the real one instead of a copy. I want copy. Can someone explain the difference between these guys?

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

Update: Here is the snippet I'm working on.

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

I need to make sure exeErrorlevel has a copy of the errorlevel at a certain point in time - I only want to capture errors from the exe, not from the success/failure of tasklist/find/taskill. I'm concerned that exeerrorlevel, because of the delayed expansion, is accessing the delayed errorlevel upon execution. perhaps that should be set exeErrorlevel=%errorlevel% instead. In the line where i echo older and newer variables usually return different integers? In all my test runs %errorlevel% seems to typically return 0 whereas !errorlevel! is consistently non zero for executables with bad exit codes.

推荐答案

错误级别

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

errorlevel is the name of a dynamic variable (it is not placed in the environment block but hold in memory) that stores the exit code of the previous executed process/command (if it sets that value, read here, here, here and here).

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

The if command allows the usage of the if errorlevel n syntax to check if the value of the errorlevel variable is greater than or equal to n, without involving the batch parser into retrieving the value of the variable.

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

But, if we put the batch parser to work with variable values, %errorlevel% is just a reference to the value stored in the variable, a read operation. Just the same as !errorlevel!. The main difference between the two is when the value is retrieved depending on the rules on variable expansion.

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

There is a great difference in using the if errorlevel or retrieving the value in the variable:

  • 变量读取操作将检查环境块是否包含具有指定名称的变量.
  • if构造函数不会进行此测试.
  • The variable read operation will check if the environment block contains a variable with the indicated name.
  • The if constuct will not make this test.

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

If you do something like set errorlevel=10, the dynamic errorlevel value will not be retrieved with %errorlevel% or !errorlevel! as the value set in the environment will hide the dynamic value. But as if errorlevel does not read the environment block but directly reads the internal variable that holds the value, it will work without problems.

变量

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

The batch syntax does not include the option of having more than one variable pointing to the same value in memory in a way that if one of the variables changes its value, the other will reflect the change.

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

This behaviour can be simulated by proper use of the different phases in variable expansion, properly setting a variable to the name of another and forcing the batch parser to do two passes over the command so first variable is resolved to the name of the second and that to the real value.

您的问题

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

Simplified (non even working) code just for analysis

 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%变量读取操作,并替换为变量内部的值.这意味着,如果变量更改了其值,则由于不存在读取操作,因此将无法检索更改后的值,而只能获取变量中的初始值.

    • line 1: the code in the do clause, all the code, is parsed. Any %var% variable read operation is removed from the code, replaced with the value inside the variable before starting the execution. This means that if the variable changes its value you will not be able to retrieve the changed value as the read operation does not exist, only the initial value in the variable.

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

      line 3: the executable is launched, in a separate process, without waiting for the process to end. Is it important? See next line

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

      line 4: the current (delayed expansion used) value of the errorlevel variable is retrieved and stored in exeErrorlevel variable. BUT the value stored is NOT the errorlevel returned by the executable (separate process, not waiting for it to end, how will we know what the exit code = errorlevel is?), but the exit code of the start command.

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

      line 6: as the %errorlevel% read operation was removed, this line will echo the value that was stored in the errorlevel variable before the do clause started to execute.

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

      line 7: the current value of the errorlevel variable is retrieved. And here, we can have a problem. How the script being executed is named? There is a difference between .bat and .cmd. On sucess the set command in line 4 will clear (set to 0) the errorlevel variable if this is a .cmd file, but will not change the errorlevel if it is a .bat file.

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

      lines 11, 14, 21: as seen the exeErrorlevel variable does not contain a valid value. And no, changing the lines to !errorlevel! will not retrieve the exit code of the process, but the exit code of the taskkill.

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

      To be able to retrieve the exit code / errorlevel of a process we need to wait for it to end. If you need to start the process, if it keeps running kill it, and in both cases retrieve the exit code, directly call the executable or use start "" /wait programName, AND run the killing process in parallel (ex. start /b "" monitor.bat programName or something similar before starting the program). The main process will wait and retrieve the exit code. The monitor process handles the killing.

      这篇关于ERRORLEVEL与%ERRORLEVEL%与感叹号ERRORLEVEL感叹号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆