中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [转]DOS的标准输入输出详解(附例解)
作者:
标题: [转]DOS的标准输入输出详解(附例解) 上一主题 | 下一主题
hackate
中级用户





积分 228
发帖 125
注册 2008-8-25
状态 离线
『楼 主』:  [转]DOS的标准输入输出详解(附例解)

DOS的标准输入输出通常是在标准设备键盘和显示器上进行的,利用重定向,可以方便地将输入输出改向磁盘文件或其它设备。其中:
1.大于号“>”将命令发送到文件或设备,例如打印机>prn。使用大于号“>”时,有些命令输出(例如错误消息)不能重定向。
2.双大于号“>>”将命令输出添加到文件结尾而不删除文件中已有的信息。
3.小于号“<”从文件而不是键盘上获取命令所需的输入。
4.>&符号将输出从一个默认I/O流(stdout,stdin,stderr)重新定向到另一个默认I/O流。例如,command >output_file 2>&1将处理command过程中的所有错误信息从屏幕重定向到标准文件输出中。标准输出的数值如下所示:
标准输出 等价的数值
Stdin 0
Stdout 1
Stderr 2
其中,1和2都创建一个文件用于存放数据;

一个有意思且有意义的现象,因为未见于公开的官方文档,所以它似乎是介于未公开特性与程序算法漏洞之间的存在。
经过简单测试得到以下结论:
这个现象由句柄二次重定向所引起,与语句的命令主体无关;
二次重定向的目标可以不同,前次重定向影响本语句,后次重定向影响语句结束后的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是可读可写,其它未见定义。复制句柄的同时,也复制了句柄的读写属性。

============例子============
@echo off
echo. 1>nul 3>2.txt
for /f %%i in (1.txt) do set /p n=%%i<nul
echo. 1>con 4>con
echo 已书写完毕!
pause
============================

---------总结---------------
所以上面的 echo. 1>nul 3>2.txt
首先将标准输出1定向到空设备nul,相当于丢掉,然后将3定向到2.txt
因为3是未定义句柄,所以会影响后面的语句for /f %%i in (1.txt) do set /p n=%%i<nul 的输出全部输出到了2.txt文件
接下来echo. 1>con 4>con
这里将标准输出定义到了标准控制台con,然后4定向到控制台con
注意这里是4,因为上面提过“后次重定向的句柄必须是未定义句柄,且必须在前次重定向之前未曾使用过”,刚才3已经用过了;这样之后的语句的标准输出就又到了控制,相当于恢复了环境


无意间在BAIDU看到的一个帖子,觉得对新人,菜鸟类似于我这样刚接触批处理不久的菜鸟们是个不错的基础至少,对于DOS的输入输出有个基本性的了解..

还请各位高手多指教哈!

2008-10-10 13:50
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hackate
中级用户





积分 228
发帖 125
注册 2008-8-25
状态 离线
『第 2 楼』:  

如上,我有个问题一直以来未曾明白,还请多多帮忙..
如下:

pause >nul
那么想请问下,如此情况下,>nul并没有指定句丙,那默认情况是1吗???
就是等同于
pause 1>nul是吗?

2008-10-10 13:53
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
HAT
版主





积分 9023
发帖 5017
注册 2007-5-31
状态 离线
『第 3 楼』:  

你从baidu转的,baidu从cn-dos转的?
http://www.cn-dos.net/forum/viewthread.php?tid=16942#pid115971



2008-10-10 13:55
查看资料  发短消息 网志   编辑帖子  回复  引用回复
HAT
版主





积分 9023
发帖 5017
注册 2007-5-31
状态 离线
『第 4 楼』:  Re 2楼

http://www.cn-dos.net/forum/viewthread.php?tid=34909#pid235843



2008-10-10 14:03
查看资料  发短消息 网志   编辑帖子  回复  引用回复
hackate
中级用户





积分 228
发帖 125
注册 2008-8-25
状态 离线
『第 5 楼』:  

晕.真没看到这个帖子,惭愧,
现在好好看看去

2008-10-10 14:09
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
everest79
金牌会员

一叶枝头,万树皆春



积分 2564
发帖 1127
注册 2006-12-25
状态 离线
『第 6 楼』:  


Dim WshShell, oExec, input
Set WshShell = CreateObject("WScript.Shell")
Set oExec    = WshShell.Exec("test.bat")
input = ""

Do While True

     If Not oExec.StdOut.AtEndOfStream Then
          input = input & oExec.StdOut.Read(1)
          If InStr(input, "Press any key") <> 0 Then Exit Do
     End If
     WScript.Sleep 100
Loop

oExec.StdIn.Write VbCrLf

Do While oExec.Status <> 1
     WScript.Sleep 100
Loop




49206C6F766520796F752067757973 54656C3A3133383238343036373837
2008-10-10 14:11
查看资料  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: