Board logo

标题: [数值计算] 批处理怎样实时传递参数? [打印本页]

作者: bluewing009    时间: 2011-6-9 19:28     标题: 批处理怎样实时传递参数?

比如:计数bat
  1. :beginrem 其他命令set /a n1+=1goto begin
复制代码
想由一个a.bat调用上面的计数bat并能实时将n1数据传回给a.bat显示



我的思路:新建一个临时文件或者环境变量,通过这个来实时获取
作者: CrLf    时间: 2011-6-9 19:35

不必使用临时文件,可以利用exit /b命令传递
a.bat:
  1. set start=%time%
  2. ping /n 2 localhost >nul
  3. ::要执行的命令
  4. call b.bat %time%
  5. echo 间隔为%errorlevel%
  6. pause
复制代码
b.bat:
  1. set /a 间隔=%1-%start%
  2. ::计时函数我就不写了哈
  3. exit /b %间隔%
  4. ::exit /b后跟数字时,将以%errorlevel%变量的形式传递回父进程
复制代码

作者: bluewing009    时间: 2011-6-9 19:42

2# zm900612
e 倒是忘了 exit /b 了
不过,
call 不是等待结束后才继续运行么?

其实我想做个类似于多进程的东西.....可能语言表述不是很好

由a.bat启动分配需要执行的命令(echo 出b.bat c.bat 等等),然后调用这些“子bat”,由a.bat实时查看各自的进度

先谢谢你提醒关于exit /b的提示,以前都是模糊的用exit  学的不深入啊,,,,
作者: CrLf    时间: 2011-6-9 19:53

多进程可以不需要分配多个bat,简单提供一个思路:
  1. @echo off
  2. %*
  3. for %%a in (ping dir move findstr) do start /b "" "%0" goto %%a
  4. pause&exit
  5. :ping
  6. ping localhost
  7. :dir
  8. dir c:\
  9. :move
  10. move %0 %tmp%
  11. :findstr
  12. findstr "^:" %0
  13. rem 以上为各个模块,执行完毕后再call :计时
  14. :计时
  15. rem 省略
  16. exit /b %间隔%
复制代码

作者: bluewing009    时间: 2011-6-9 20:02

4# zm900612


主要关心的是如何做到主监视子的问题(或者说是全局变量):如果我举的例子不明显的话,比如,由a启动b(已经写好),b每执行完一个命令,a显示+1
作者: CrLf    时间: 2011-6-9 20:05

那好像没特别好的办法了...
无非临时文件、tasklist计算cmd进程数、环境变量等等
作者: bluewing009    时间: 2011-6-9 20:17

6# zm900612


比如说,环境变量,哪个bat都能使用的,但是自己set一个值,另一个就不能获取了。所以我原本的思路就是借助临时文件或者自定义一个环境变量,这样效率上有问题,特别是临时文件…………有没有什么变量像环境变量一样“共享”?
作者: CrLf    时间: 2011-6-9 20:41

忽然想起来,qzw好像说过环境变量是cmd启动时从explorer获取的,所以启动之后应该不接受新的环境变量了吧?没试过,不知道

至于别的方法,虽然有,不过我知道的方法都不如临时文件
作者: bluewing009    时间: 2011-6-9 22:01

8# zm900612


临时文件的话需要实时读写,效率不高,关于环境变量,记得用wmic可以立即生效的,原先发帖时记得搜索过,关键字“环境变量”。
作者: qzwqzw    时间: 2011-6-9 23:17

Windows应用程序的环境变量(包括cmd.exe)继承自创建它的父进程
并继续传递给它创建的子进程

wmic可以改变全局变量
但是其效率甚至不如临时文件
因为它要写注册表
并且广播窗口消息到所有窗口
其它能够改变全局变量的方法无不类似
作者: bluewing009    时间: 2011-6-10 00:12

10# qzwqzw


请问你有什么好办法呢?另,为什么说不如临时文件?如果是临时文件作计数用岂不是要实时读写硬盘?
作者: caruko    时间: 2011-6-10 01:06

临时文件也不是很好,因为多个进程访问同一个文件会出现IO错误。

我一般是用 AT 命令来设置不会被执行的命令,顺便把需要传递的值带过去。

如,b.bat
写入 at 1:00 /next:%date:-2% @b.bat@var1@var2@var3.....

a.bat
读取 for /f "tokens=1,2* delims=@" %%a in ('at') do set 来自%%b的值=%%c



还有一个办法,wmic监视事件日志中指定事件ID的日志消息。
然后B.BAT执行添加日志操作命令 "eventcreate" ,具体用法可eventcreate /?
作者: qzwqzw    时间: 2011-6-10 21:38

wmic由于自身的机制启动将会很慢
与setx.exe作对比测试了一下
wmic environment耗时是wmic的两倍多

临时文件的性能其实并没有你想象的那么不堪
性能是wmic environment的数百倍

当然如果你考虑到共享冲突而无法选择此方案
还可以选择用Reg add/query操作注册表
它的性能是wmic environment的10+倍
作者: cjiabing    时间: 2011-6-11 10:37

12# caruko


你小子想像力超人啊!at都想得出来!难能可贵!
前阵子和某某谈过这个话题,不过也没更好的方法。
好像我做过试验,用title也可以解决问题,将数据实时写到窗口标题,然后使用tasklist提取。这个tastlist可以在需要时提取,也可以使用start  /b实时监视。
这个我还是比较熟练,但手机无法提供例子。
作者: bluewing009    时间: 2011-6-11 20:22

13# qzwqzw


注册表项!感觉这个要好一些,从上面各位朋友的回答来看,都是用一个文件或者某个标志作为计数器,这样的话,子进程要实时读写这个标记,主进程也要实时读取这个标记,都在一直占用资源。总感觉还是不怎么好,最好是能够传递……不知道怎么说好…………就是说,子进程执行一条命令后,告诉主进程,没通知就等待,就是有点像中断……呼呼……不知道这样说能不能解释清楚
作者: caruko    时间: 2011-6-12 16:22

TITLE 的办法有想过,但一时没想到tasklist 可以提取。
这也的确是个办法,但是同步问题不好解决,因为title没有缓存,读取的内容可能在2次读取的时间断中,被新的数据覆盖了,导致部分丢失。
作者: qzwqzw    时间: 2011-6-12 16:49

是的
注册表项读写实质上也是文件读写
与临时文件不同的地方就是
不需要理会文件句柄的打开和关闭

楼主说的应该是类似于Windows消息和事件触发的机制
这只有自行设计命令行程序才能实现了
作者: mxxcgzxxx    时间: 2011-6-14 11:08

可以用doskey啊生成命令在另一个批处理中执行获取参数,应该非常快吧!
示范下,不过我只在自己内部调用意思下,
doskey 调定的是全局命令不关机都不会消失
  1. @echo off
  2. 1:
  3. set /p a=猜猜我是谁:
  4. if %a%==5 doskey aaa=set bbb=你真厉害啊 $*
  5. aaa
  6. echo %bbb%
  7. pause>nul
  8. doskey aaa=
  9. goto 1:
复制代码

作者: qzwqzw    时间: 2011-6-14 21:22

18# mxxcgzxxx
不知楼上是如何测试的?
doskey的宏只能在cmd当前进程中生效
在平行的cmd.exe进程中是相互独立的
那如何实现cmd进程间的通讯呢?

设想可以通过进程互斥子的方式
实现共享内存式的进程通讯
但实现起来比较麻烦
已经脱离批处理比较远了




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2