[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[系统相关] 请问2个BAT之间传递参数的问题(2个都设置本地为延迟扩展)后的问题

通过测试论坛中两个bat之间如何在运行时实时接受和处理参数?,我已经基本理解原理,但是:

如果我的两个bat文件内部的业务逻辑都需要设置本地为延迟扩展,然后传参和取参数就会有问题,举例来说,如下:
【1】1.bat调用2.bat
【2】2.bat返回IP地址给1.bat
【3】1.bat 再去根据业务需要加工IP处理业务(略)
---------------------------------------------------------
代码如下:

1.bat
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. CALL "%~dp0\2.bat" "myIP"
  4. ECHO 测试1-%myIP%
  5. ECHO 测试2-!myIP!
  6. @REM 后面的业务逻辑也需要处理for语句,所以1.bat文件也要开启【设置本地为延迟扩展】
  7. pause
复制代码
2.bat
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. @REM 逻辑判断一下过来的参数名称
  4. if "%~1"=="myIP" Call :getIP
  5. ::if "%~1"=="myIP" set myIP=127.0.0.1
  6. if "%~1"=="myIP" set myIP=%IP%
  7. goto :eof
  8. :getIP
  9. @REM
  10. @REM 中文系统一般是:本地连接
  11. @REM 笔记本没有以太网卡的时候,中文系统一般是:WLAN
  12. set "AdapterName=WLAN"
  13. set "FileTmp=%temp%\ipList.txt"
  14. ipconfig /all >"%FileTmp%"
  15. for /f "delims=:" %%i in ('findstr /n /c:"%AdapterName%" "%FileTmp%"') do (
  16.     set "SkipRow=%%i"
  17.     goto :DoSkip
  18.     goto :eof
  19. )
  20. goto :eof
  21. :DoSkip
  22. for /f "tokens=2 delims=:(" %%i in ('more +%SkipRow% "%FileTmp%" ^| findstr /v "IPv6" ^|findstr "IP"') do (
  23.     set "IP=%%i"
  24.     goto :ShowResult
  25.     goto :eof
  26. )
  27. :ShowResult
  28. REM 格式化数据(清除空格)
  29. set "IP=%IP: =%"
  30. ::endlocal
  31. ::goto :eof
  32. echo.
  33. echo -----------------------------------------------------------
  34. ECHO 当前选择的网络适配器的名称是:!AdapterName!
  35. ECHO 当前选择的网络适配器IP地址是:%IP%
  36. echo -----------------------------------------------------------
  37. echo.
  38. pause
  39. goto :eof
复制代码
-------------------------------------------

然后,运行1.bat
输出结果为:
  1. 当前选择的网络适配器的名称是:WLAN
  2. 当前选择的网络适配器IP地址是:192.168.1.6
  3. 请按任意键继续. . .
  4. 测试1-
  5. 测试2-
  6. 请按任意键继续. . .
复制代码
-------------------------------------------

说明:2.bat是拿到了IP地址但是,返给1.bat的时候,数据没有了

------------------------------------------
我修改了2.bat的代码,将:2.bat的setlocal enabledelayedexpansion取消后,反而运行正常了,有些不太明白,因为2.bat我还要做些别的处理,需要【置本地为延迟扩展】,所以这句话还不能注释掉,所以请大神们给看一下怎么回事,谢谢啦!!!!

而且setlocal enabledelayedexpansion再win10上运行与win7上运行是否有差异啊?

我注释掉2.bat的setlocal enabledelayedexpansion这句话之后,win10是可以了,但是win7还是没有数据,晕死了!!!!

我的笔记本没有以太网卡,只有无线网卡,所以各位调试上面的代码的时候,可以将:
set "AdapterName=WLAN"
修改为:
set "AdapterName=本地连接"

或者改成你们具体的网卡适配器的名称就可以了!

TOP

我把1.bat的setlocal enabledelayedexpansion和2.bat的setlocal enabledelayedexpansion都注释掉之后

本机(win10 ) [版本 10.0.18363.1500] 的运行行结果是:
  1. -----------------------------------------------------------
  2. 当前选择的网络适配器的名称是:本地连接
  3. 当前选择的网络适配器IP地址是:192.168.145.1
  4. -----------------------------------------------------------
  5. 请按任意键继续. . .
  6. 测试1-192.168.145.1
  7. 测试2-192.168.145.1
  8. 请按任意键继续. . .
复制代码
-----------------------------------------------------------
虚拟机(win7 ) [[版本 6.1.7601]] 的运行行结果是:
  1. -----------------------------------------------------
  2. ------
  3. 当前选择的网络适配器的名称是:!AdapterName!
  4. 当前选择的网络适配器IP地址是:192.168.152.143
  5. -----------------------------------------------------
  6. ------
  7. 请按任意键继续. . .
  8. 测试1-192.168.152.143
  9. 测试2-!myIP!
  10. 请按任意键继续. . .
  11. C:\Users\GLY>
复制代码
-----------------------------------------------

请问:
setlocal enabledelayedexpansion
这句话是不是再win10he win7上是有差异的啊?

TOP

好像看明白点问题:
1.bat
  1. ECHO 测试1-%myIP%
  2. ECHO 测试2-!myIP!
复制代码
在win10系统这两种写法都是支持的
无论有没有setlocal enabledelayedexpansion这句话的加持都能输出的样子啊

但是在win7系统中,如果取消掉【设置本地为延迟扩展】也就是把【setlocal enabledelayedexpansion】注释掉,就只能输出:用%变量%的形式了,然后!变量!这种形式,没有【设置本地为延迟扩展】就不行

所以,在win7系统【setlocal enabledelayedexpansion】注释掉,就连【当前选择的网络适配器的名称是:!AdapterName!】这句话都当做是字符串输出了,根本就没办法解析变量,

那么,怎么才能开启【设置本地为延迟扩展】这个后正常运行代码,并且确保也能win7和win10的系统正确运行呢?

TOP

本帖最后由 newswan 于 2021-6-29 11:09 编辑

回复 4# ChinaTB


   在 2.bat中
  1. endlocal & set %1=%myIP%
复制代码

TOP

回复  ChinaTB


   在 2.bat中
newswan 发表于 2021-6-29 10:37



    谢谢,大佬!!

--------------------------------

问题已经解决了,我改成:
  1. endlocal & set %~1=%IP%
复制代码
换行写成:
  1. endlocal
  2. set %~1=%IP%
复制代码
都是可以的了,不过原理还是不太明白,网上搜索了一下文章:《BAT批处理文件 setlocal,endlocal命令详解》

里面说:
setlocal和endlocal命令执行结果是让中间的程序对于系统变量的改变只在程序内起作用,不会影响整个系统级别。

应该是不去写 endlocal 不关闭,才可以全局使用的意思吧,我i什么我endlocal反而才能生效啊?
那么:
批处理中setlocal enabledelayedexpansion,在什么情况下去endlocal 才是好的习惯呢?能都给详细解释一下原理啊?谢谢!!!!

TOP

不好意,我懂了!
《批处理中setlocal enabledelayedexpansion的作用详细整理》

https://www.jb51.net/article/29323.htm
-----------------------------------------------
字面意思,就是

set:设置
local:本地(环境变量)
enable:能够
delayed:延迟
expansion:扩展
setlocal enabledelayedexpansion就是扩展本地环境变量延迟,

所以:
setlocal和endlocal

就是开始设置本地(环境变量)设置和 结束本地(环境变量)设置的意思

所以,我的问题是没有在【2.bat】结束本地(环境变量)的设置,那么就意味着【1.bat】就无法拿走全局的%myIP%, 而[!myIP!]是只能2.bat访问的,虽然2.bat中
  1. if "%~1"=="myIP" set myIP=%IP%
复制代码
判断了1.bat给过来的参数名,正确后,并给myIP这个变量,也就是1.bat传过来的第一个参数【%~1】赋值了,但是由于没有endlocal,导致1.bat接收不到变量(就只能输出空)或者直接显示:【ECHO 处于关闭状态。】

-----------------------------------------

但是,win10 和 win7 不一样的问题,着实没搞明白,虽然加了endlocal问题也绝了,但是为啥:取消setlocal enabledelayedexpansion这句话,win10 可以运行,而 win7 不能运行呢?

TOP

本帖最后由 newswan 于 2021-6-29 14:48 编辑

回复 7# ChinaTB

简单的说,是变量作用域。
整个是全局作用域
setlocal 到 endlocal 之间是一个作用域。
这个局部作用域内,
如果有全局变量,在局部作用域内可以得到全局变量的值,但如果改变了这个变量,只在局部作用域中有效,全局变量的值不会改变
如果要在局部作用域内修改全局变量,可以在 “endlocal 语句组” 中 在 “endlocal 语句 之后”给变量赋值。
注意 是 “endlocal 语句组” “endlocal 语句组” “endlocal 语句组”

可以是
  1. endlocal & set a=%a%
复制代码
可以是
  1. (
  2. endlocal
  3. set a=%%a
复制代码
麻烦在于,局部作用域中所有变量都是局部的,要修改全局变量,必须  在退出局部区域时  给每个全局变量重新赋值。
好处在于,局部代码最好从一个地方退出,不能随便跳到外部,有利于规范

测试
  1. @echo off
  2. set va="xxx"
  3. echo "g1:" %va%
  4. setlocal enabledelayedexpansion
  5. rem call 2.bat va
  6. set va=xxxx
  7. echo,
  8. echo "l1:" %va%
  9. (
  10. endlocal disabledelayedexpansion
  11. set va=%va%
  12. )
  13. echo,
  14. echo "g2:" %va%
  15. (
  16. setlocal enabledelayedexpansion
  17. set va=%va%
  18. )
  19. echo,
  20. echo "l2:" %va%
  21. endlocal disabledelayedexpansion
复制代码
win7 没有开启变量延迟时, ! 只是普通字符,   !a!  不表示变量值

TOP

谢谢大佬!

收获新知识啦!
  1. (
  2. endlocal
  3. set a=%%a
复制代码
这个括号很重要,我之前没注意到这个问题,把:
  1. endlocal & set a=%a%
复制代码
分行处理,没有加括号,就又失败了,如果设置变量多最好还是用分行的写清楚一些,括号很重要!!!!!括号很重要!!!!!括号很重要!!!!!

TOP

返回列表