标题: [其他] 在call的子程序中直接调用主程序的疑惑 [打印本页]
作者: qzwqzw 时间: 2012-4-18 11:47 标题: 在call的子程序中直接调用主程序的疑惑
- @echo off
- if [%1]==[call] (echo 在批处理主程序中运行 & exit /b)
- set prog=%0
- call :子程序
- echo.end
- pause
- goto :eof
-
- :子程序
- if [%1]==[call] (echo 在批处理子程序中运行 & exit /b)
- echo.%0---%~s0---%~f0
- rem 以下调用将程序的命令行指针转向了子程序而非主程序
- rem 这跟我以前的用法和认识相违背,是哪里出了问题?
- %prog% call
复制代码
作者: powerbat 时间: 2012-4-18 12:32
我知道%0并不一定表示批处理“文件”路径,而是实际键入的“程序”名(包括标签名),但可以用%~f0、%~s0等扩展成文件路径,曾经的verybat论坛有相关帖子论述。
也知道调用bat子程序时,如果不加call,调用位置后面的代码将无法执行。- main.bat
- ==========
- @echo off
- echo;begin
- sub.bat
- rem call sub.bat
- echo;到这里了
- echo;end
- pause
-
- sub.bat
- ==========
- echo.%0---%~s0---%~f0
- pause
复制代码
ntcmds.chm中对call的解释
Call
从一个批处理程序调用另一个批处理程序,并且不终止父批处理程序。
不使用call有点类型于linux的exec,子程序把当前程序给替换了?
楼主的代码加一个call就正常了,但不明白不加时为什么是那样的结果。难道cmd重调用bat时记住了“子程序”在文件中的偏移位置,直接从偏移处开始执行代码?
作者: neorobin 时间: 2012-4-18 14:20
测试得到一些结果:复制代码
在子过程中被解释成标号行, 而在主程序(文件级)中始终被解释成调用自身.
另外, 用 %0 作赋值的情况:
set prog=%0 处于 | %prog% callParams | !prog! callParams |
在子过程中 | 标号行 | 标号行 |
在主程序(文件级)中 | 调用子过程自身 | 调用主程序(文件级) |
测试代码:- @echo off
- REM echo %%0 Params
- REM (%0 Params) & rem 将调用主程序(文件级)自身, 而陷入死循环
-
- setlocal enabledelayedexpansion
- echo,& echo,@ Main code & echo,
- echo,%%0=%0
- echo,Params=%*
-
- if [%1]==[Params] (echo 在批处理主程序中运行 & exit /b)
-
- (set prog=%0) & rem 处于主程序(文件级)中
- echo prog=%prog%
-
- echo,call :子程序
- call :子程序
-
- echo,& echo,End of Main code & echo,
- pause
- goto :eof
-
- :子程序
- echo,& echo,@ Sub code & echo,
- echo,%%0=%0
- echo,%%~s0=%~s0
- echo,%%~f0=%~f0
- echo,Params=%*
- if [%1]==[Params] (echo 在批处理子程序中运行 & exit /b)
-
- echo prog=%prog%
-
- echo,%%0 Params
- %0 Params
- REM 上行被解释成标号行
-
- REM (set prog=%0) & rem 处于子过程中
- echo prog=%prog%
- echo,^^!prog^^! Params
- !prog! Params
-
- echo,%%prog%% Params
- %prog% Params
-
- echo,& echo, end of sub code & echo,
- exit /b
复制代码
作者: qzwqzw 时间: 2012-4-18 21:38
经过与原来的代码对比
终于发现了不同之处- @echo off
- if [%1]==[call] (echo 在批处理主程序中运行 & pause & exit /b)
- call :子程序1
- echo.
- call :子程序2
- echo.
- echo.主程序结束
- pause
- goto :eof
-
- :子程序1
- if [%1]==[call] (echo 在批处理子程序2中运行 & pause & exit /b)
- echo 以下调用将程序的命令行指针转向了主程序,区别在于调用发生在一个子句中
- echo if [1]==[1] %~f0 call
- if [1]==[1] %~f0 call
-
- :子程序2
- if [%1]==[call] (echo 在批处理子程序1中运行 & pause & exit /b)
- echo 以下调用将程序的命令行指针转向了主程序,区别在于调用发生在一个语句块中
- echo ^( %~f0 call ^)
- ( %~f0 call )
复制代码
另外谈一下为什么要用这个特性
我主要用它做子程序的错误抛出处理
也就是说在某个被call的子程序中
如果发现错误就使用 "%~s0 :Error 错误代码 错误信息" 的形式
把这个错误抛出到程序的错误处理模块中
当然这个错误需要在程序的起始位置加一句错误捕捉语句
if [%1]==[:Error] goto :Error
之所以不用call抛出错误
是因为我在处理了错误之后是不准备返回子程序的
而是直接使用 exit /b 错误代码 的形式退回了主程序
原来一直使用本楼的写法
即在直接调用之间都会有一些判断语句
所以没有遇到问题
因此就形成了刻板的印象
没想到call中的%~s0调用会重置到子程序的起始位置
作者: applba 时间: 2012-4-20 22:42
%0返回的最近的调用者。
作者: qzwqzw 时间: 2012-4-21 23:03
回复 5# applba
不解其意
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |