Board logo

标题: [已结]批处理语句中的 2>nul 1>nul 是什么意思 [打印本页]

作者: xjhlhb     时间: 2005-9-12 11:31    标题: [已结]批处理语句中的 2>nul 1>nul 是什么意思

本人从华大科技下载一自动升级批处理文件,其中语句如rmdir /S /Q %mhnet% 2>NUL 1>NUL中两个>NUL是何意思呢?不是很明白,请教高手赐教,谢了!

---------- Edited by willsort  ----------
修改原标题:请教:批处理文件语句问题?
---------- Edited by willsort ----------



请教:批处理文件语句问题?
原文件如下:
@echo offrem 使用介绍
rem 功能:试图设置自动连接华科大Windows Update服务器
rem 先进行服务检查,没有安装服务的机器先安装服务,重启动后再修改设置

echo [INFO] For Windows 2000,Windows XP,Windows 2003 only.
echo [INFO] 只在Windows 2000,Windows XP,Windows 2003 上适用
echo [INFO] For Normal user only (computer that runs every day)
set Server=0
rem Server=1
pause
cls

rem 创建临时文件夹
set mhnet=%temp%\mhnet
rmdir /S /Q %mhnet% 2>NUL 1>NUL
mkdir %mhnet%

rem 系统语言环境判断
reg query HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language >%mhnet%\Language.log
find "Default" %mhnet%\Language.log |find "0804" >NUL
IF NOT ERRORLEVEL 1 (
set Language=Chinese
) else (
set Language=English
)

if %Language%==Chinese (
echo [INFO] 本程序专为设置华科大 Windows Automatic Updates 服务
) else (
echo [INFO] This will setup HUST Windows Automatic Updates Services
)

start readme.txt

rem 检查配套文件完整性
call :AllFiles

rem 检查属于NT系列
call :CheckSystem

rem 检查拥有管理员权限
call :CheckAdmin

rem 检查Automatic Updates服务是否正常安装
call :CheckService

call :HUSTRegImport


if %Language%==Chinese (
echo [INFO] 程序讨论,欢迎到 bbs.whnet.edu.cn security版
echo [INFO] 程序结束
) else (
echo [INFO] We welcome you to press your opinion on  bbs.whnet board:security
echo [INFO] Program Exit
)

pause
set mhnet=
set patchfile=
set downloadurl=
goto :eof
exit
:ends
rem 主函数结束




rem *************************
rem *************************
rem 导入:HUSTRegImport
rem *************************
rem *************************
:HUSTRegImport
ECHO [INFO] 备份注册表(Backup Reg) %temp%
pushd %temp%
set BakFile1=AutoUpdateBak1.reg
set BakFile2=AutoUpdateBak2.reg
if exist %BakFile1% (
ECHO [INFO] 已经安装了本补丁,按任意键删除原有备份
PAUSE
delete %BakFile1% /f /q >NUL 2>NUL
delete %BakFile2% /f /q >NUL 2>NUL
)
popd

pushd %mhnet%
reg EXPORT "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" %BakFile1% 1>NUL
reg EXPORT "HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate" %BakFile2% 1>NUL
move %BakFile1% %temp% >NUL
move %BakFile2% %temp% >NUL
set BakFile1=
set BakFile2=
popd

ECHO [INFO] 正在停止WindowsUpdate服务(Stopping Update service)......
net stop wuauserv >NUL 2>NUL

ECHO [INFO] 正在修改注册表操作(Modifying Registry)......
ECHO Y |reg DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /va /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate /v WUServer /t REG_SZ /d "http://windowsupdate.hust.edu.cn" /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate /v WUStatusServer /t REG_SZ /d "http://windowsupdate.hust.edu.cn" /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoRebootWithLoggedOnUsers /t REG_DWORD /d 1 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoUpdate /t REG_DWORD /d 0 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v RescheduleWaitTime /t REG_DWORD /d 1 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v ScheduledInstallDay /t REG_DWORD /d 0 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v UseWUServer /t REG_DWORD /d 1 /f >NUL



if %Server%==1 (
ECHO [INFO] Automatic Updates Service installed for server
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v AUOptions /t REG_DWORD /d 4 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v ScheduledInstallTime /t REG_DWORD /d 11 /f >NUL
) else (
ECHO [INFO] Automatic Updates Service installed for non-server
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v AUOptions /t REG_DWORD /d 2 /f >NUL
reg add HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU /v ScheduledInstallTime /t REG_DWORD /d 12 /f >NUL
)

rem 服务自动启动
ECHO [INFO] 设置服务为自动启动(Set service to automatic start)
reg add HKLM\SYSTEM\CurrentControlSet\Services\wuauserv /v Start /t REG_DWORD /d 2 /f >NUL
reg add HKLM\SYSTEM\CurrentControlSet\Services\BITS /v Start /t REG_DWORD /d 2 /f >NUL

ECHO [INFO] 正在重新启动WindowsUpdate服务(Starting Update Service)......
net start bits >NUL 2>NUL
net start wuauserv >NUL 2>NUL

goto :eof







rem *************************
rem *************************
rem 停止/删除服务函数
rem *************************
rem *************************
:StopService
set SrvName=%1
net stop %SrvName% >NUL >NUL2
reg query HKLM\SYSTEM\CurrentControlSet\Services\\%SrvName% >NUL
if not errorlevel 1 (
reg delete HKLM\SYSTEM\CurrentControlSet\Services\\%SrvName%  /f >NUL
) ELSE (
if %Language%==Chinese (
  echo [FAIL] 系统服务: %SrvName% *没找到*
) else (
  echo [FAIL] System Service: %SrvName% Not Found
)
)
goto :eof






rem *************************
rem *************************
rem 判断是否NT系列系统,win9x系统则退出
rem *************************
rem *************************
:CheckSystem
if NOT %OS%==Windows_NT (
if %Language%==Chinese (
  echo [INFO] 本程序专为中文/英文版本的Win2000,WinXP,Win2003设计
  echo [FAIL] Windows 95, Windows 98, Windows ME的用户不必运行
  echo [INFO] 程序退出。
) else (
  echo [INFO] Design for Win2k,WinXP,Win2003 with Chinese or English version only.
  echo [FAIL] Windows 95,Windows 98, Windows ME will not be troubled by this bug.
  echo [INFO] Thank you for checking. Please deliver this to someone who need it.
)
pause
exit
) else (
if %Language%==Chinese (
  echo [INFO] 用户使用基于WindowsNT内核的系统,
) else (
  echo [INFO] You are using a system based on WindowsNT kernel,
)
)
goto :eof



rem *************************
rem *************************
rem 判断是否NT系列系统,win9x系统则退出
rem *************************
rem *************************
:CheckAdmin
net user %username%  1> %mhnet%\ifadmin.log
rem 如果不是系统管理员
find "*Administrators " %mhnet%\ifadmin.log >NUL
IF ERRORLEVEL 1 (
if %Language%==Chinese (
  echo [FAIL] 用户不是系统管理员组成员 ,不能执行相应程序
  echo [INFO] 请更换有足够权限的用户重新运行本程序
) else (
  echo [FAIL] This program require administrator right to continue
  echo [INFO] Please switch user and try again
)
pause
exit
goto :eof
) else (
if %Language%==Chinese (
  echo [INFO] 用户属于系统管理员组,
) else (
  echo [INFO] You have got the right of administrator,
)
)
goto :eof






rem *************************
rem *************************
rem 先进行补丁检查,没有安装补丁的机器先安装补丁,重启动后再查杀病毒
rem *************************
rem *************************
:CheckService
rem if %Language%==Chinese (
rem  echo [INFO] 检查 Automatic Updates
rem ) else (
rem  echo [INFO] Checking Automatic Updates Service
rem )
rem 检查服务的注册表值

reg query "HKLM\SYSTEM\CurrentControlSet\Services" >%mhnet%\Services.log
find "wuauserv" %mhnet%\Services.log >NUL

IF ERRORLEVEL 1 (
rem 您的计算机未安装Automatic updates服务
call :InstallService
pause
exit
rem 中止执行
) ELSE (
rem  if %Language%==Chinese (
rem   echo [INFO] 注册表检查显示您的系统已经安装了wuauserv服务。
rem  ) else (
rem   echo [INFO] reg reports that your system has wuauserv service installed
rem  )
)
goto :eof







rem *************************
rem *************************
rem 清空注册表某\Run值
rem *************************
rem *************************
:CleanRun
reg delete HKLM\Software\Microsoft\Windows\CurrentVersion\Run\\%1 /f >NUL
goto :eof








rem *************************
rem *************************
rem 停止不安全服务
rem *************************
rem *************************
:StopUnSafeSrv
rem net stop %1 >NUL
reg add HKLM\SYSTEM\CurrentControlSet\Services\\%1 /v Start /t REG_DWORD /d 0x3 /f >NUL
goto :eof








rem *************************
rem *************************
rem 导入正常注册表的execute文件关联
rem *************************
rem *************************
:Regdefault
reg import regdefault.reg >NUL
goto :eof




rem *************************
rem *************************
rem 安装wuauserv包
rem *************************
rem *************************
:InstallService
rem reg query HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language >%mhnet%\Language.log

rem 中文系统
find "InstallLanguage" %mhnet%\Language.log |find "0804" >NUL
IF NOT ERRORLEVEL 1 (CALL :CNService )

rem 英文系统
find "InstallLanguage" %mhnet%\Language.log |find "0409" >NUL
IF NOT ERRORLEVEL 1 (CALL :ENService )

rem 其他语言包,以上语言包虽用call调用,但不希望返回
if %Language%==Chinese (
echo [FAIL] 你并未使用中文/英文操作系统,
echo [INFO] 请记下下面显示的InstallLanguage及Default的值,请到微软网站下载相应服务
echo [INFO] 程序退出
) else (
echo [FAIL] You are not using windows with Chinese/English language
echo [INFO] We suggest you download the service from microsoft website.
echo [INFO] Please write down the InstallLanguage & Default value for later use.
echo [INFO] program terminated
)
find "InstallLanguage" %mhnet%\Languate.log
start http://www.microsoft.com/downloa ... &DisplayLang=en
rem 微软服务安装网页
pause
exit
goto :eof







rem *************************
rem *************************
rem 中文服务包下载安装
rem *************************
rem *************************
:CNService
set patchfile=WUAU22CHS.msi
set downloadurl=http://windowsupdate.hust.edu.cn/patch/%patchfile%
call ownload
start %mhnet%\%patchfile%
if %Language%==Chinese (
echo [INFO] 安装好服务后重启电脑,再运行本程序
) else (
echo [INFO] Restart your computer when Service installation is done. And run again.
)
pause
exit
goto :eof








rem *************************
rem *************************
rem 英文服务包下载安装
rem *************************
rem *************************
:ENService
set patchfile=WUAU22ENU.msi
set downloadurl=http://windowsupdate.hust.edu.cn/patch/%patchfile%
call ownload
start %mhnet%\%patchfile%
if %Language%==Chinese (
echo [INFO] 安装好服务后重启电脑,再运行本程序
) else (
echo [INFO] Restart your computer when Service installation is done. And run again.
)
pause
exit
goto :eof









rem *************************
rem *************************
rem 检查部分文件完整性
rem *************************
rem *************************
:AllFiles
if not exist reg.exe (
echo [WARN] reg.exe NOT FOUND
pause
exit
) else (
copy reg.exe %mhnet% /y >NUL
)

if not exist wget.exe (
echo [WARN] wget.exe NOT FOUND
pause
exit
) else (
copy wget.exe %mhnet% /y >NUL
)
goto :eof





rem *************************
rem *************************
rem 下载补丁,用%patchfile%传入文件名
rem *************************
rem *************************
ownload
if %Language%==Chinese (
  echo [INFO] 自动下载 %downloadurl%
) else (
  echo [INFO] Downloading %downloadurl%
)
pushd %mhnet%
if exist %patchfile% (
  del %patchfile% /f /q >NUL 2>NUL
)
wget %downloadurl%
IF NOT ERRORLEVEL 1 (
  if %Language%==Chinese (
   echo [INFO] 下载成功。
  ) else (
   echo [INFO] Download Success
  )
) else (
  if %Language%==Chinese (
   echo [FAIL] 下载失败。程序退出
  ) else (
   echo [FAIL] Download Failed. Terminated
  )
  pause
  exit
)
popd
goto :eof



rem ----- this is the end of this batch file -------

[ Last edited by willsort on 2006-5-13 at 18:28 ]
作者: willsort     时间: 2005-9-12 13:06
Re xjhlhb:

      详细代码尚在学习中,仅就你提到的语句 rmdir /S /Q %mhnet% 2>NUL 1>NUL 做简单解释。

      这句代码的大意是指将 %mhnet% 指定的目录删除,/s 代表删除其中的子目录, /q 表示删除目录树时不提示确认, 1>nul 表示将正确删除目录树的信息禁止输出,2>nul 表示将删除过程中的错误信息禁止输出。

     其中的1与2都是代表某个数据流输入输出的地址(NT CMD 称之为句柄,MSDOS称之为设备),下表(引自WinXP帮助文档“使用命令重定向操作符 (Redirection Operators”一节))将列出可用的句柄。

  Quote:
句柄 句柄的数字代号 说明
STDIN 0 键盘输入
STDOUT 1 输出到命令提示符窗口
STDERR 2 错误输出到命令提示符窗口
UNDEFINED 3-9 这些句柄由应用程序和各个具体工具单独定义。


───────────────── 版主提示 ─────────────────
红色字体所示内容,目前认定为错误言论,敬请注意!
───────────────── 版主提示 ─────────────────


[ Last edited by willsort on 2006-3-24 at 08:48 ]
作者: xjhlhb     时间: 2005-9-14 16:39
感谢2楼高手的解答,看来如此命令是完全正确的了!
通过如此批处理,我们总结如下:1 REG可以读取注册表信息 ; 2 CALL可以调用本文件内命令段 ; 3 GOTO可以转移到文件的尾部 ; 4 >NUL可以制定信息流的方向

另外:请教:如何通过批处理判断系统是95/98或者2000/XP呢??????
作者: pillow     时间: 2005-12-13 11:54
这个程序太好了!
让我学到很多东西!
希望可以经常有这样的贴子,建议建立一个类似程序的集中营,有兴趣的人可以为没有注释的程序加上注释,这样我们可以少问很多问题的
作者: willsort     时间: 2006-3-24 12:01    标题: 重定向原理

Re All:

    在此首先对2楼提到的某些言论予以纠正和补充,望周知。上文中涉及的在CMD中称为“句柄”的1,2等数字代号,在MSDOS与9x COMMAND下没有定义,也与“设备”概念无关。
==============================================
    “重定向”是自MSDOS起就被支持的命令行特性,负责将指定命令或语句所产生的输入输出请求由缺省的“控制台”转交给其它的“设备”来完成,它的启动标志是“重定向符号”(包括“>,>>,<”三个,其各自意义见[1])出现在句中。

    一般的命令行程序输入输出请求都通过内部定义三个“端口”(在NT下称为“句柄”,在DOS下未定义)来完成,分别为标准输入stdin、标准输出stdout、标准错误stderr。它们通常指向的设备为控制台(console,代码为CON),其中stdin指向控制台的键盘,stdout/stderr指向控制台的监视器。因此,控制台通常即指键盘与监视器的联合体,这是在早期大型机的终端机上所体现出来的概念。其中的stdin可被<重定向,stdout可被>、>>重定向,而stderr在DOS下不可直接重定向,只有通过ctty或其它命令将系统控制权转交给其它设备的方式,来间接完成。

    “设备”是指可控制PC硬件或端口的设备驱动程序或端口代码,它通常由系统底层或硬件驱动程序实现和支持。比如IO.SYS实现的控制台CON、系统时钟CLOCK$、未知设备CONFIG$、第一串口AUX、第一并口PRN、所有串口COM1~COM4、所有并口LPT1~LPT3、可用盘符A:-X:以及上文提到的空设备NUL。还有许多其它设备,比如HIMEM.SYS实现的XMSXXXX0,EMM386.EXE实现的EMMXXXX0,IFSHLP.SYS实现的IFS$HLP$等。
   
    在这些设备中,可以处理输入输出信息的很少,只有CON、NUL以及连接有输入输出硬件(打印机、MODEM等)的串口或并口设备。它们被称为“字符设备”,而磁盘文件也作为一种特殊的字符设备列选其中,这就大大扩充了重定向的自由度与实用性,以致很多人也将重定向称为“文件重定向”。
   
    空设备NUL是一个特殊的设备,因为它没有可控制的PC硬件或端口,而只是一个虚构的的设备或端口,它仅存在于软件层面。正因为如此,它可以接受所有重定向的输入输出请求而不给出任何回应,在NT下不会给出任何输入信息而结束输入请求,在DOS下则反复填充127个二进制字节1(显示为^A)后终止响应,这种特性使它很像天文学上的能吞噬一切物质和信息的“黑洞”,也很类似哲学上能颠转阴阳无中生有的“玄玄之道”。它之所以存在,是因为我们需要一个可以默默无闻地无条件吸纳各种冗余输出信息或输入请求的“回收站”,正如“黑洞”就像一个巨大的“宇宙垃圾场”一样。
   
    命令行对重定向符号出现的位置不做过多限定,只要重定向符号后紧随“字符设备”即可,故以下语句等效:

    echo Hello World> hello.txt
    echo Hello> Hello.txt World
    echo> Hello.txt Hello World
    > hello.txt echo Hello World

    在NT系列命令行中,重定向的作用范围由整个命令行转变为单个命令语句,受到了命令分隔符&,&&,||和语句块的制约限制。

    echo Message1> msg1.txt & echo Message2> msg2.txt
    if "%target%"=="" (echo message to screen ) else (echo message to file> %target%)
   
    综上所述,>nul 意为将此句命令所产生的标准输出请求重新定向到空设备中,而因为此设备的缄默特性,即相当于将此语句的输出信息屏蔽(并非隐藏);而 2>nul 则是将程序执行错误时的标准错误信息输出请求重定向后屏蔽。它们联合使用,即为将此语句所可能产生的所有输出信息屏蔽。

[1] 重定向命令在安全方面的攻防应用
http://www.cn-dos.net/forum/viewthread.php?tid=17578

[ Last edited by willsort on 2006-3-24 at 18:42 ]
作者: chenall     时间: 2006-3-25 20:37    标题: 请教: 关于NT批处理的问题.

我看了这篇文章后
[批处理语句中的 2>nul 1>nul 是什么意思]
http://www.cn-dos.net/forum/viewthread.php?tid=16942&fpage=1
自已试了试.发现了一个有趣的现象.

可以在NT命令行中输入以下命令实现了一些特殊的效果.
echo. 2>nul 3>nul
执行这个命令后,所有出错误提示均看不到了?

echo. 1>nul 3>nul
执行这个命令后,所有的输出提示均看不到了(但是错误提示会显示)?

这两个命令却无法同时使用.
另外也不知如何再恢复过来(除了使用EXIT退后再进入CMD)?

还有执行以下语句后将会一直循环显示,无法停上?
echo. 0>nul 3>nul

不知这些是什么原理??
作者: Climbing     时间: 2006-3-25 21:22
确实很有意思,我觉得关键在3这个设备上。不知道3代表的是什么设备。

0 应该是标准输入(键盘)
1 是标准输出(屏幕)
2 是标准错误(屏幕)

在chenall的第一个例子中,如果换成:
somecmd 2>&1
或者
somecmd 2>&3
都会显示出错误信息。

总之,这个话题确实值得探讨一下。
作者: chenall     时间: 2006-3-26 08:02
又发现一个现象
echo. 2>nul 3>test.txt
以后就会将出错信息写入到test.txt中.
同理.
echo. 1>nul 3>test.txt
就会将标准输出信息写入到test.txt中.

这个话题确实值得探讨一下。

[ Last edited by chenall on 2006-3-26 at 10:10 ]
作者: Climbing     时间: 2006-3-26 09:55
科学上的不断实践又一次证明了:1+2=3这个颠扑不破的真理。
作者: 3742668     时间: 2006-3-26 11:50


  Quote:
Originally posted by chenall at 2006-3-25 20:37:
我看了这篇文章后
[批处理语句中的 2>nul 1>nul 是什么意思]
http://www.cn-dos.net/forum/viewthread.php?tid=16942&fpage=1
echo. 2>nul 3>nul
执行这个命令后,所有出错误提示均看不到了?

echo. 1>nul 3>nul
执行这个命令后,所有的输出提示均看不到了(但是错误提示会显示)?

这两个命令却无法同时使用.
另外也不知如何再恢复过来(除了使用EXIT退后再进入CMD...

指定了2次句柄3当然无法同时使用了,把第二个改成echo. 1>nul 4>nul看看
恢复分别用echo 2>con 5>con     , echo 1>con 6>con,若是只想某一句恢复用>&,<&来复制句柄看看。
未经测试。
作者: chenall     时间: 2006-3-26 14:38
指定了2次句柄3当然无法同时使用了,把第二个改成echo. 1>nul 4>nul看看
确实可以.
恢复分别用echo 2>con 5>con     , echo 1>con 6>con,若是只想某一句恢复用>&,<&来复制句柄看看。
未经测试。
恢复不行..
当然了恢复某一句是可以使用
command 2>con 1>con的.

[ Last edited by chenall on 2006-3-26 at 14:45 ]
作者: Jneny     时间: 2006-3-26 15:56
太....深了,救我,,```
作者: willsort     时间: 2006-3-26 19:09

───────────────── 版务记录 ─────────────────
执行:Will Sort
操作:合并主题:《19735 - 请教: 关于NT批处理的问题.》
说明:二主题存在上下文的直接联系
处罚:鉴于主题具有原创性质,不予处罚
提示:请访问 {7326}论坛新手必读,所有人的基本行为准则[转帖]
───────────────── 版务记录 ─────────────────


Re chenall:

      这确实是一个有意思且有意义的主题。关于这个奇怪的现象,因为未见于公开的官方文档,所以它似乎是介于未公开特性与程序算法漏洞之间的存在。

      经过简单测试得到以下结论:

      这个现象由句柄二次重定向所引起,与语句的命令主体无关;
      二次重定向的目标可以不同,前次重定向影响本语句,后次重定向影响语句结束后的CMD环境;
      后次重定向的句柄必须是未定义句柄,且必须在前次重定向之前未曾使用过;此次使用后即刻作废,不可重复用于缺省CMD环境的句柄重定向;

      由此我对此现象的推测如下:

      在CMD中的某一语句中实现句柄的修改(重定向或者复制)时,设计者为了实现在语句执行完后,恢复被修改的句柄,则必然会在修改之前复制(或者说备份)句柄,至于备份的目的地,CMD选择了从未曾使用过的“未定义句柄(3-9)”,这似乎是一个无可厚非的选择。但是程序在判断并获取未使用句柄时显然存在某些漏洞,它们首先处理第一个修改操作,在得到要修改的句柄后,立即寻找未使用的备份句柄,在找到备份句柄并进行备份后,才处理随后的修改操作,而此时这个备份句柄仍然可以被修改,导致在语句结束后,CMD会使用修改后的备份句柄恢复第一次修改的句柄,最后导致CMD的缺省句柄被修改。而此时CMD才得知备份句柄已被使用,而会在下一语句中修改句柄时使用其后的“未使用句柄”进行备份。

      以下的语句应该也是类似的原理,只是更加准确的说明了获取备份句柄的时机。

pause 1>&3 3>nul

      所以,CMD帮助文档中关于3-9是未定义句柄的说辞,应该是不够准确的,因为它确实会被系统移作他用,而并非“由应用程序单独定义,它们是各个工具特有的”,由此看来,它更像是“保留句柄”。

      另外,CMD中句柄的行为显然更为复杂了,尤其是句柄复制的行为,即使微软的文档对此也是语焉不详。比如以下的语句可以将stdout复制到stderr,而stderr被重定向到了nul设备,结果导致pause的stdout重定向到nul设备,也即无输出。这是可理解的。

pause 2>nul 1>&2

      而在下面的语句中,仅仅将复制与重定向的操作反转,便不再有效。而这也应与以上提到的CMD特性有关。

pause 1>&2 2>nul
      
      最后需要提及的是,CMD中句柄具有读写属性,stdin是只读的,stdout是只写的,stderr是可读可写,其它未见定义。复制句柄的同时,也复制了句柄的读写属性。

[ Last edited by willsort on 2006-3-26 at 19:14 ]
作者: electronixtar     时间: 2006-5-11 13:37
强啊
作者: electronixtar     时间: 2006-5-11 13:47
怎么和Linux如此相似?
作者: Scott0902     时间: 2006-5-11 14:00
第一次看到NUL有这种用法
作者: chineselgs     时间: 2006-5-11 16:18
呵呵看了半天,就是不懂!~~
作者: arding     时间: 2006-5-12 13:17


  Quote:
Originally posted by chenall at 2006-3-26 14:38:
指定了2次句柄3当然无法同时使用了,把第二个改成echo. 1>nul 4>nul看看
确实可以.
恢复分别用echo 2>con 5>con     , echo 1>con 6>con,若是只想栮..

我们讨论的对象中都出现了两个 > ,用i,j表示0到9的数字,如果将句柄看作指向设备的指针,则默认时:
句柄          指向
stdin  [0]     con
stdout[1]    con
stderr [2]    con

当命令cnd i>nul j>nul 中的第一个>被执行时,系统将[ i]的目标暂存于未用的句柄空间,如[3],已备命令结束时恢复。然而,第二个>使得暂存的内容被修改,于是给后续命令留下了影响。
实际上,cnd i>nul j>nul 又会将[j]的原内容暂存于再一个未用空间内,所以
cnd 2>nul 3>nul 对输出的改变,能够用cnd 2>&3 4>&3恢复回来。
由于暂存位置由系统选择,作为用户无法左右,所以数值不能肯定。
(我的每次试验为了保证句柄空间的确定,都是重新进入cmd.)
作者: willsort     时间: 2006-5-13 18:49
Re arding:

  Quote:
由于暂存位置由系统选择,作为用户无法左右,所以数值不能肯定

我在13楼中猜测,cmd将其修改前的句柄存放在“从未访问过的未定义句柄中(3-9)”。这里再明确一下,其中的“从未访问过”,是指在当前的cmd命令行中用户从未显式指定过,而并非cmd本身未使用过,而“从未访问过”的句柄可能有多个,而cmd会选择第一个。如果你有反面的例证,不妨提出。
作者: willsort     时间: 2006-5-14 17:15
Re arding:

      我自己得到了反证,在执行了以下两句后,命令行仍然被屏蔽了。

      echo test 3>nul
      echo test 1>nul 3>nul

      也就是说,我们尽管在第一句中已经访问了句柄3,但仍然可以在第二句中使用3>nul来改变备份的句柄stdout[1]。

      因此,cmd的句柄备份策略可能是这样:首先使用未定义句柄3,如果检测到这个句柄处在备份状态时被改动,则换用下一个句柄。

      另外还有一些发现:

      1、cd 1>nul 2>nul 3>nul 4>nul 可以直接改变stdout和stderr的输出;
      2、cd 0<nul 3<nul 或者 cd 0<nul 3>nul 将导致cmd不断回显命令行提示;
      3、cd 0<nul 3<file 则直导致 cmd 窗口被关闭;
      4、cd 1>nul 3>nul 后,cls 的行为也会失效,因此确证cls也是一种输出行为;

       最后,关于句柄的复制,实际上可以理解为句柄的重定向,只是此次重定向的目标不再是设备或者文件,而是另一个句柄。

       打个比方说,设备或文件是一个蓄水池,句柄就是其管道,命令则是管道上的水泵或者过滤器,而cmd就是一个自成一体的水循环系统。水池的管道从0-9编号,共有10条,0#管为进水管,1#管为排水管,2#管为故障测试管,3-9#管则是未使用的备用管。而0<实际上是打开进水管的阀门,1>则是打开排水管的阀门,而1>&2则打开将1#管到2#管的连接阀。而>nul的则是用水泵将水扬空。
作者: arding     时间: 2006-5-15 11:38
Re Willsort:
      通过反复试验,可以猜测系统的句柄使用策略,比如

  Quote:
cnd 2>nul 3>nul 对输出的改变,能够用cnd 2>&3 4>&3恢复回来。

一句中的 4 便是猜测的结果,这也是基于刚刚进入cmd,句柄的使用情况比较清楚地情况下的猜测。
      如果在一个批处理中反复使用了句柄重定向,则难以判断其句柄空间的情况,所以我说“系统决定,用户难以左右”。
      我同意你的关于“未用句柄”的概念,测试也证实了这个概念。实际上,我感觉到明确的概念至关重要,反之则贻害无穷。就像windows帮助那些似是而非的说明,只会使人更加糊涂。
作者: weilong888     时间: 2006-10-12 08:00
顶上去。
作者: pengfei     时间: 2006-10-12 09:47
经典, 又扩展思路了, 句柄重定向!
作者: soker     时间: 2006-10-12 10:15
看不懂啊~   努力ing......
作者: qq82015930     时间: 2006-10-12 11:41
爱我还看不懂
作者: lxmxn     时间: 2006-10-12 13:34

    两位实在是令人敬佩,但最终给人的感觉,还是没有明确说明句柄重定向的原理,尽管举了几个例子。

作者: electronixtar     时间: 2006-10-12 21:55
知道有这回事就行啦。不懂的看Linux Shell入门
作者: jinnee     时间: 2006-10-14 03:41
看了这篇文章大长见识,不过还希能有高手来指点大家,顶一下
作者: jianyaogao     时间: 2007-3-17 20:29
深奥,理解中
作者: axi     时间: 2007-3-18 01:43
哗!这些学识是从哪里学的呢,高深到极!
作者: 81291895     时间: 2007-3-18 03:35
强贴
不顶都不行
作者: 371770923     时间: 2007-5-29 17:28
set mhnet=%temp%\mhnet
rmdir /S /Q %mhnet% 2>NUL 1>NUL
mkdir %mhnet%
请问楼主,这里的%mhnet%是指文件夹名为temp吗??还是含有temp的文件夹?
请楼主就上面的几句做具体解释
谢谢!!
作者: rockdong     时间: 2007-8-31 17:02
逛了一天,收获不小。:lol:
作者: hanchanzhu     时间: 2007-9-17 11:34
太深奥了,什么时候能懂啊。
作者: picat     时间: 2007-9-18 21:23
留个脚印,日后慢慢消化~~
作者: jhyjml     时间: 2007-9-19 20:35
强啊
作者: Billunique     时间: 2007-9-21 19:03


  Quote:
空设备NUL是一个特殊的设备,因为它没有可控制的PC硬件或端口,而只是一个虚构的的设备或端口,它仅存在于软件层面。正因为如此,它可以接受所有重定向的输入输出请求而不给出任何回应,在NT下不会给出任何输入信息而结束输入请求,在DOS下则反复填充127个二进制字节1(显示为^A)后终止响应,这种特性使它很像天文学上的能吞噬一切物质和信息的“黑洞”,也很类似哲学上能颠转阴阳无中生有的“玄玄之道”。它之所以存在,是因为我们需要一个可以默默无闻地无条件吸纳各种冗余输出信息或输入请求的“回收站”,正如“黑洞”就像一个巨大的“宇宙垃圾场”一样。

  精到!......
作者: wordexport     时间: 2007-10-5 10:33
不错不错
作者: 422904z     时间: 2007-10-9 19:23
顶一下
作者: huanghourun     时间: 2007-10-11 01:34
可读性强~!
作者: eghawk     时间: 2007-10-15 17:55
我一直见过这样的东东,这次看到了
作者: rocmagic     时间: 2007-10-16 18:30
有点深了,难懂啊
作者: ztwaker     时间: 2008-1-22 13:15
不错:)
作者: flyfox1047     时间: 2008-1-30 17:58
强呀,收藏下,以后慢慢品位
作者: csx163     时间: 2008-1-31 02:18
这个NUL和NULL有区别否?有则区别在哪里?
作者: VAF     时间: 2008-2-1 04:35
岂止是深, 还很玄妙呢.
作者: heyaowei124242     时间: 2008-2-9 13:03
看不懂啊 ,,,...
作者: hsyxh     时间: 2008-2-14 20:56
看得不明白,只知道>nul 可以屏蔽屏幕的正确输出
>nul 2>nul"可以屏蔽一切屏幕的输出
作者: zyz0304360     时间: 2008-2-16 14:27
好贴,收藏起来
作者: juventus     时间: 2008-3-22 21:41
学习了
还有些看不明白
努力学习中
作者: zljzsm     时间: 2008-5-17 03:30
似懂非懂    头晕啊  慢慢实践吧     先记下来
作者: zljzsm     时间: 2008-5-17 03:35
真不知道有些人一上论坛就“强啊”“牛啊”的乱回复一通是为了什么。几乎每进一个话题就可以看到几个这样的人。刚刚学得起劲的时候看到这样的回复真是恼火。
作者: sxqylz     时间: 2008-5-17 08:06
哎,看得一愣一愣的
作者: taqiao     时间: 2008-5-18 11:32
俺是新手,以后再看吧
作者: driver1998     时间: 2008-5-25 11:37
3楼:
可以用VER加find,就像这样:

title 检查Windows 版本
ver|find "5.1.2600" > nul
if "%ERRORLEVEL%"=="1" goto noxp
作者: 23112656     时间: 2008-7-31 18:15
爽啊```看着这些文章就是有股未知的冲动
作者: 23112656     时间: 2008-7-31 18:15
爽啊```看着这些文章就是有股未知的冲动
作者: dejoy     时间: 2008-11-15 12:09


  Quote:
Originally posted by xjhlhb at 2005-9-14 04:39 PM:
感谢2楼高手的解答,看来如此命令是完全正确的了!
通过如此批处理,我们总结如下:1 REG可以读取注册表信息 ; 2 CALL可以调用本文件内命令段 ; 3 GOTO可以 ...

请参考以下链接:

(已结)如何通过批处理判断系统是95/98或者2000/XP呢
http://www.cn-dos.net/forum/viewthread.php?tid=16963