[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
猜测句柄 4~9 的初始值不是有效句柄
做了一个测试试图证明当初始句柄不是有效句柄时,产生的备份句柄会保留,却得到了奇怪的结果:


A、测试中 3 和 4 为备份句柄:
3=1,4=2
而结束备份后句柄 4 仍无效
  1. echo test >nul 2>nul
  2. echo 无效句柄 1>&4 2>con
复制代码
B、
测试中 3、4、5 为备份句柄:
3=1,4=2,5=3
结束备份后句柄 4 变成 3 所备份的状态
  1. echo test >nul 2>nul 3>nul
  2. echo 变成句柄3(nul) 1>&4 2>con
复制代码
  1. echo test >nul 2>nul 3>con
  2. echo 变成句柄3(con) 1>&4 2>con
复制代码
C、
测试中 3、4、5 为备份句柄:
3=1,4=2,5=3
结束备份后句柄 4 变成 nul
既不是 3 也不是 2,违背测试 C 体现的规律
  1. echo test >nul 2>&1 3>&1
  2. echo 变成 nul 1>&4 2>con
复制代码
D、
这两个测试中 3、4、5 为备份句柄:
3=1,4=2,5=3
结束备份后句柄 4 变成 1 的原始状态
  1. echo test >nul 3>nul 4>nul
  2. echo 正确 1>&4 2>con
复制代码
E、
这两个测试中 4、5 为备份句柄:
4=3,5=4
结束备份后句柄 4 仍是无效句柄
  1. echo test 3>nul 4>nul
  2. echo 错误 1>&4 2>con
复制代码

TOP

有人能看出 16 楼测试结果的隐含规律吗?

TOP

本帖最后由 CrLf 于 2014-11-28 20:26 编辑

发现前面的说法有误,比较以下三个测试:
  1. dir 4>&3
复制代码
  1. dir >nul 4>&3
复制代码
  1. dir 1>&3
复制代码
看来句柄 3~9 的初始状态都是无效句柄
是先发生备份(想过去这也是理所当然的),句柄 3 保存了句柄 1 的值,再执行了 1>&3,把句柄 3 的值借给句柄 1,命令执行完毕后,句柄 3 把备份还给句柄 1,所以看起来句柄 3 仿佛默认等于句柄 1 的初始状态

TOP

把以前的老帖翻出来炒冷饭
  1. :: 句柄模拟.cmd - 模拟运算句柄操作后的句柄状态
  2. :: qzwqzw - 2009-6-12
  3. @echo off & setlocal EnableDelayedExpansion
  4. if [%1]==[] (
  5.     echo. 这是句柄操作示例, 模拟运算进行几次句柄操作后的句柄状态
  6.     echo --------------------- call %~n0 ">nul" "2>nul" ---------------------
  7.     call %0 ">nul" "2>nul"  
  8.     set 句柄
  9.     echo.
  10.     echo --------------------- call %~n0 ">nul" "2>nul" "3>nul" ---------------------
  11.     call %0 ">nul" "2>nul" "3>nul"  
  12.     set 句柄
  13.     echo.
  14.     echo --------------------- call %~n0 ">nul" "2>&1" "3>&1" ---------------------
  15.     call %0 ">nul" "2>&1" "3>&1"  
  16.     set 句柄
  17.     echo.
  18.     echo --------------------- call %~n0 ">nul" "3>nul" "4>nul" ---------------------
  19.     call %0 ">nul" "3>nul" "4>nul"  
  20.     set 句柄
  21.     echo.
  22.     echo --------------------- call %~n0 "3>nul" "4>nul" ---------------------
  23.     call %0 "3>nul" "4>nul"  
  24.     set 句柄
  25.     echo.
  26.     pause
  27.     goto :eof
  28. )
  29. set "0=con" & set "1=con" & set "2=con"
  30. for %%h in (%句柄%) do set %%h
  31. echo.----- 起始状态 Initiation state -----
  32. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  33. echo.
  34. echo.----- 预处理 Pre-process -----
  35. :loop
  36. if [%1]==[] goto :end
  37. echo.----- %1 -------
  38. set "_tmp=%~1"
  39. if "%_tmp:~0,1%"=="<" set "_tmp=0%_tmp%"
  40. if "%_tmp:~0,1%"==">" set "_tmp=1%_tmp%"
  41. set _句柄=%_tmp:~0,1%
  42. set _句柄_2=
  43. set _dev=
  44. if "%_tmp:~2,1%"=="&" (set _句柄_2=%_tmp:~3%) else (set _dev=%_tmp:~2%)
  45. for %%h in (0 1 2 3 4 5 6 7 8 9) do (
  46.     if "!%%h!"=="" (
  47.         set/p=b: %_句柄%[!%_句柄%!]=^>%%h[!%%h!] : <nul
  48.         set "%%h=!%_句柄%!"
  49.         set bak_%%h=%_句柄%
  50.         goto :set
  51.     )
  52. )
  53. :set
  54. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  55. echo.
  56. if defined _dev (
  57.     set/p=a: %_dev%=^>%_句柄%[!%_句柄%!] : <nul
  58.     set %_句柄%=%_dev%
  59. ) else if defined _句柄_2 (
  60.     set/p=a: %_句柄_2%[!%_句柄_2%!]=^>%_句柄%[!%_句柄%!] : <nul
  61.     set %_句柄%=!%_句柄_2%!
  62. )
  63. for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  64. echo.
  65. shift
  66. goto :loop
  67. :end
  68. echo.----- 后处理 Post-process -----
  69. for %%h in (0 1 2 3 4 5 6 7 8 9) do (
  70.     if not "!bak_%%h!"=="" (
  71.         set/p=r: !bak_%%h![]^<=%%h[!%%h!] : <nul
  72.         set !bak_%%h!=!%%h!
  73.         set %%h=
  74.         set bak_%%h=
  75.         for %%h in (0 1 2 3 4 5 6 7 8 9) do set/p=%%h=!%%h! <nul
  76.         echo.
  77.     )
  78. )
  79. set 句柄=
  80. for %%h in (0 1 2 3 4 5 6 7 8 9) do set 句柄=!句柄! "%%h=!%%h!"
  81. endlocal & set 句柄=%句柄%
  82. echo.----- 结束状态 End Status -----
  83. for %%h in (%句柄%) do set/p=%%~h <nul
  84. echo.
复制代码
1

评分人数

    • CrLf: 先加分再研究~技术 + 1
天的白色影子

TOP

回复 14# qzwqzw


    举那个例子可能有点不合适,因为(echo,|cls)>con与cls>con是一样的效果,但是下面这两句就不一样了。
  1. (echo,|echo,)>con
复制代码
  1. echo,>con
复制代码
但是若用句柄备份的思想来看待这个问题的话,那么可以再把这里的错位再还原回去:
  1. (echo,|echo,)>con 1>&3
复制代码
它们表现出的现象何其相似,并且可以用这个方式来解释出现的原因并将之还原回去,所以我才说所谓的句柄备份是否背后的原因也是触发了你这里面提到的模式置换。

TOP

回复 20# amwfjhh
  1. (echo,|echo,)>con 1>&3
复制代码
相同句柄的重定向只以最后一次为准,经过预处理,这里实际执行的重定向只有 1>&3,而句柄 3 是句柄 1 的备份,所以句柄 1 的重定向结果还是原来的句柄 1

TOP

回复 21# CrLf


    说的不错。我的理解是:
  1. (cls|echo,)>con
复制代码
当命令的执行结果被重定向到下一个非接收流的命令,并且过程被括起来重定向到con后,其实是相当于标准输出被重定向到了数据流,而数据流又被重定向到了con(这个非原始标准输出),则所有的输出内容都被看着流数据对待,特殊控制字符不再有其原始的控制效能,比如清屏,beep等,这个时候的输出内容就有点类似于debug的d命令右边显示字符的那块了,所有字节被看成普通文本对待,能显示就显示,不能显示留空跳过。当然它们的具体显示效果不同。

TOP

返回列表