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

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

问题描述

我想我对 ERRORLEVEL 与 %ERRORLEVEL% 有基本的了解,但是 !ERRORLEVEL!让我困惑.

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

我正在制作一个调用可执行文件的脚本,然后是 tasklist 以查看它是否正在运行,然后 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!对于具有错误退出代码的可执行文件,始终为非零.

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% 读取操作,该行将回显存储在 errorlevel 变量中的值在 do 子句开始执行.

      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.

      为了能够检索进程的退出代码/错误级别,我们需要等待它结束.如果你需要启动进程,如果它一直运行kill它,并且两种情况都检索退出代码,直接调用可执行文件或使用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 vs %ERRORLEVEL% vs 感叹号 ERRORLEVEL 感叹号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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