Board logo

标题: [讨论]如何判断cmd的echo 处于开启还是关闭状态? [打印本页]

作者: plp626    时间: 2011-6-18 19:37     标题: [讨论]如何判断cmd的echo 处于开启还是关闭状态?

这个问题在调试代码时比较有用,只是看似简单的问题,并不简单;
用for /f 抓取的并不是当前的环境,和doskey/h问题很相似。

不知大家有什么高招?(最好别生成临时文件)
作者: ipqfhvk    时间: 2011-6-18 20:14

这个问题很好解决嘛
echo>1.txt
你打开1.TXT看到什么?
@echo off
echo>1.txt
你又看到了什么
。知道了吗???
作者: CrLf    时间: 2011-6-18 22:49

本帖最后由 zm900612 于 2011-6-18 22:50 编辑

前几天搞文件头加密那个帖子时也愁过这个,没想到除了临时文件外的更好办法
  1. @((for %%a in (test) do echo test)>tmp
  2. for /f "skip=2" %%a in (tmp) do @set echo=1
  3. if defined echo (echo;on) else echo;off)
复制代码

作者: CrLf    时间: 2011-6-19 13:33

2# ipqfhvk


预处理回显不属于句柄1的输出内容,所以需要通过for /f将其转换为能从句柄1输出的命令执行结果中的回显
作者: tmplinshi    时间: 2011-6-19 13:54

本帖最后由 tmplinshi 于 2011-6-19 15:20 编辑
  1. if "%1" == "echo" echo & exit
  2. for /f "tokens=*" %%a in ('%0 echo') do set status=%%a
  3. set status
  4. pause
复制代码

作者: CrLf    时间: 2011-6-19 14:16

if "%1" == "echo" echo & exit
for /f "tokens=*" %%a in ('%0 echo') do set status=%%a
set status
pause
tmplinshi 发表于 2011-6-19 13:54


漂亮!
作者: CrLf    时间: 2011-6-19 15:32

这个问题很好解决嘛
echo>1.txt
你打开1.TXT看到什么?
@echo off
echo>1.txt
你又看到了什么
。知道了吗???
ipqfhvk 发表于 2011-6-18 20:14


本以为说的是思路,原来这就是实际可行的代码,以前没有留意过单独的echo在判断回显是否开启时的用途,学习了!
作者: Hello123World    时间: 2011-6-19 16:06

这有什么实际意义吗?获取预处理的回显?
作者: caruko    时间: 2011-6-20 12:28

不一定要 for 抓取吧?
findstr不就行了?
作者: mxxcgzxxx    时间: 2011-6-20 14:28

  1. for /f "tokens=2" %%1 in ('echo') do echo %%1
  2. pause
复制代码

作者: tmplinshi    时间: 2011-6-20 16:12

本帖最后由 tmplinshi 于 2011-6-20 17:52 编辑
for /f "tokens=2" %%1 in ('echo') do echo %%1
pause
mxxcgzxxx 发表于 2011-6-20 14:28


'echo' 会开启一个新的 cmd.exe 进程来输出信息,是通过 cmd.exe /c echo 传递给 for 的。
但是并不等同于 'cmd /c echo',这样系统仍会处理成 cmd.exe cmd /c echo

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

不一定要 for 抓取吧?
findstr不就行了?
caruko 发表于 2011-6-20 12:28


我之前确实没有想到用 findstr。但刚才测试了一下,这样也会启动新的 cmd 进程。

经测试,如果是 echo a | echo b,系统会启动两个 cmd:
    cmd.exe /S /D /c" echo a "
    cmd.exe /S /D /c" echo b"

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

以上结论是用 Process Monitor 监测到的。大家可以自己监测一下,打开软件后在“过滤器”里设置只监测 cmd.exe 进程。
作者: CrLf    时间: 2011-6-20 16:58

'echo' 会开启一个新的 cmd.exe 进程来输出信息,是通过 cmd.exe /c echo 传递给 for 的。
但是并不等同于 'cmd /c echo',这样系统仍会处理成 cmd.exe cmd /c echo。

------------------------------------ ...
tmplinshi 发表于 2011-6-20 16:12


我原以为只有从语块中获取输入时才会启动新的cmd,现在看来应该是当管道前后存在内部命令或者管道中存在语块时会启动新的cmd,所以现在有了新的看法:
  1. @echo off
  2. echo|findstr 关闭
  3. ::等于cmd /c echo|findstr 关闭,启动了新cmd,所以echo始终处在打开回显的状态
  4. (tasklist)|find /i "cmd"
  5. ::当存在语块时,需要cmd来解释其语句的划分,所以启动了新cmd也是可以理解的
  6. tasklist|(find /i "cmd")
  7. ::同上
  8. (tasklist)|(find /i "cmd")
  9. ::这条证明了管道前后同时被预处理,并分别在不同的cmd中解释语句
  10. tasklist|find /i "cmd"
  11. ::都是外部命令,而且不存在语块,所以不启动新cmd
复制代码

作者: qzwqzw    时间: 2011-6-20 18:10

12# zm900612
哪有如此复杂
简而言之
管道必然会开启新进程
扩展开来
管道是将后一个进程的输入句柄指向前一个进程的输出句柄
而对于内部命令来说
是不存在独立的操作句柄的
所以必然会启动其宿主程序cmd.exe
作者: qzwqzw    时间: 2011-6-20 18:15

5# tmplinshi
程序具有很大局限性
比如下面的程序
虽然可能通过一定的代码构造大致解决这个问题
但这不是最佳的方案
  1. @echo off
  2. if "%1" == "echo" echo & exit
  3. echo on
  4. for /f "tokens=*" %%a in ('%0 echo') do set status=%%a
  5. set status
  6. pause
复制代码
最佳的方案仍然是临时文件(2楼的方案)
简单、有效并且适用面广
不明白楼主为何不看好这个方案
是否楼主也有非TMP的情结?
作者: cjiabing    时间: 2011-6-21 13:20

  1. echo
  2. @Echo off
  3. echo
  4. pause
  5. echo ------------------
  6. @echo on
  7. echo |findstr "打开"
  8. @echo off
  9. echo |findstr "关闭"
  10. pause
  11. echo ------------------
  12. @echo on
  13. echo >nul
  14. echo >nul 2>nul
  15. echo ------------------
  16. @echo off
  17. echo >nul
  18. echo >nul 2>nul
  19. pause
  20. echo ------------------
  21. @echo on
  22. echo &&echo ok
  23. echo||echo no
  24. echo ------------------
  25. @echo off
  26. echo &&echo ok
  27. echo||echo no
  28. pause
  29. echo ------------------
  30. @echo on
  31. echo |findstr "打开"
  32. echo 1
  33. echo |findstr "关闭"
  34. echo 2
  35. @echo off
  36. echo |findstr "打开"
  37. echo 3
  38. echo |findstr "关闭"
  39. echo 4
  40. pause
  41. echo ------------------
复制代码

作者: garyng    时间: 2011-12-2 12:17

这个?
  1. for /f "delims=" %%i in ('echo') do (echo %%i)
复制代码
也会开多几个进程内!
为什么?
作者: CrLf    时间: 2011-12-2 15:54

回复 16# garyng


    for /f 从命令获取输入的时候,其实是将 (' ') 中的内容传递给 cmd /c,
  1. for /f "delims=" %%a in ('tasklist /nh /fi "imagename eq cmd.exe"') do echo %%a
  2. ::可以看到新开了一个 cmd 进程
  3. for /f "delims=" %%a in ('echo %%cmdcmdline%%') do echo %%a
  4. ::可以看到其命令行参数
复制代码

作者: garyng    时间: 2011-12-2 16:21

回复 17# CrLf


神奇也~
我到for中的‘’是创建另一个进程来执行的也~
我一直以为是但单进程的也~

又长知识了~
作者: BS0小陈    时间: 2011-12-2 18:36

菜鸟不知所云~~~~~:




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