Windows进程内标准输出重定向
- 格式:doc
- 大小:32.50 KB
- 文档页数:3
Windows进程内标准输出重定向及其在程序调试上的应用一、如何实现打印调试信息的方法有很多,最常用的是使用标准输出设备(如printf、cout等),也可以用OutPutDebugString输出、用DebugView工具查看,还可以写入日志文件。
如果程序运行需要记录日志(log),往往需要打开个文件,或许是写入系统事件、用系统的事件查看器查看。
应用程序打印调试信息、日志的方法往往是确定的,但如果是要编写一个模块或者说组件,那样的输出信息应该写入哪里呢?或者说程序本身对此也没有明确需求的话,那该怎么办呢?可喜的是一个进程的标准输出是可以重定向的,所以我建议把调试信息直接打到标准输出上,这样代码中可以统一使用cout或者printf,然后根据需要将标准输出重定向。
Linux中重定向标准输出就容易了,因为有强大的dup2函数。
而对于Windows的重定向,貌似往往是用于子进程的,在用CreateProcess创建子进程时设置子进程的标准输出句柄。
而我们想要的是重定向自己这个进程的标准输出,那个用不上。
我在MSDN中也没找到类似dup2的Win32 API函数,只有一个DuplicateHandle函数,这相当于linux中的dup,也用不上。
这里顺便提下,SetStdHandle是不能实现重定向的。
这个函数的功能是将某句柄指向标准设备,并不能将标准设备句柄重定向到另外的句柄。
于是我就想到,Windows不是支持一部分POSIX标准的吗。
于是我找到了一个CRT的函数,叫_dup2,看起来是不是特眼熟,对了,这就是Windows中dup2的兼容版本。
值得注意的是,_dup2以及与此相关的一系列CRT中的IO函数(如_read,_write)均以下划线开头,其余与linux大致相同,其参数中所谓的文件描述符与Win32中的句柄不一样,文件描述符实际上是句柄数组的索引,也就是说文件描述符不能与句柄混用。
比如0,1,2分别是标准输入、标准输出、标准错误的文件描述符,但句柄值不是这样确定的。
谈谈重定向、管道与C我所知道的重定向和管道就这些了,写了一早晨终于写完了,现在接着睡,希望对大家有用。
这是我学习之中知道的一些关于重定向和管道的知识,并积累的资料,在这里和大家分享。
如果说的有不足和错误的地方,请指出。
毕竟是交流信息。
我这里是从DOS和C语言方面看它,没有太多涉及LINUX中所说的。
我想从以下几个方面叙述:一、重定向:所谓重定向,就是不使用系统的标准输入端口、标准输出端口或标准错误端口,而进行重新的指定,所以重定向分为输出重定向、输入重定向和错误重定向(注:STDIN 0 标准输入键盘命令在执行时所要的输入数据通过它来取得STDOUT 1 标准输出显示器命令执行后的输出结果从该端口送出STDERR 2 标准错误显示器命令执行时的错误信息通过该端口送出)。
通常情况下重定向到一个文件。
重定向命令又称转向命令。
其中错误重定向和输出重定向有些类似,就不多说,学过C++可能会明白的多些。
所谓输出重定向指把执行相应DOS命令时本应在屏幕上显示的内容输出到重定向命令所指向的文件或设备中去。
输出重定向命令> 、>>。
它们的区别是:如果你使用的是> ,原文件会被删除,重新生成新的文件,其内容如上所述;如果你使用的是>> ,它以追加的方式,将命令的输出写入文件的末尾,原文件内容会被保留,新的内容会添加到原文件件的内容的后面。
主要用在某个命令的输出很多,在屏幕上不能完全显示,就可把它重定向到一个文件中,稍后再用文本编辑器来打开这个文件。
输入重定向使输入信息来自文件。
如果一个名为的文件C:>file 之后,执行file时所需的处理信息就改为由文件file读入,这就是输入重定向。
小于号<是输入重定向操作符,在<之后的文件名或设备名是重定向的输入源。
如果一个程序时需要输入较多数据,使用输入重定向可以提高效率。
在这里要说一些过滤命令more 、sort 和find 。
信息运维人员岗位技术普考强化培训试题(主机类题)姓名单位分数一、单选题(每题0.5分,80道题,共计40分)1. 命令 ls -l list | more的输出最终显示在哪里?A. list文件中B. 终端屏幕上C. root目录中D. 系统缺省打印机上2. 假如当前目录不在PATH中,如何执行当前目录的可执行文件foo?A. fooB. ../fooC. ./fooD. /foo3. 如何显示系统当前所有的进程?A. psB. pshC. ps –fD. ps -ef4. 如果路径中以/开头,则意味着?A. 相对路径B. 绝对路径C. 当前目录D. 父目录5. 如何使用一个文件做为命令的输入?A. 重定向输入B. 追加输入C. 重定向输出,再重定向输入D. 在命令行中输入文件的内容6. ls中用哪个选项可以显示文件的类型?A. ls -FB. ls -lC. ls -RD. ls -c7. 在vi中,如何进行编辑模式并在当前光标前插入字符?A. aB. iC. $D. o8. 显示所有mount上来的文件系统的可用空间?A. dfB. df /C. duD. du /9. 用哪个键可以中断一个进程的运行?A. Ctrl-cB. Ctrl-qC. Ctrl-xD. Ctrl-z10. 如何删除文件Machine*.$CLUSTER.txt?A. rm Machine*.*$CLUSTER.txtB. rm "Machine*.$CLUSTER.txt"C. rm 'Machine*.$CLUSTER.txt'D. rm "Machine\*.$CLUSTER.txt"11. 当前目录是/tmp,哪个命令可以显示当前目录所在的文件系统的可用空间?A. df .B. du $tmpC. du .D. df $tmp 12. 在aix系统中,可以通过以下哪个命令查看pv的信息?A.pvdisplayB.lspvC.lsvg -o|lsvg –ilD.lsdev –Cc disk13. 在vi中,保存文件但不退出的命令是?A.:wqB.:wC.:xD.ZZ14.在AIX系统中,fileset名为“Bos.terminfo.print.data”,请指出该fileset中得package是什么?A.BosB. terminfoC. printD. data15. 如何回到用户的主目录?A.cdB.pwdC.cd ../homeD. cd ./home16. 日志文件logfile动态更新,如何实时查看logfile?A. more logfileB. cat -v logfileC. more logfileD. tail -f logfile17. 下面哪个是Linux中合法的文件名?A.-GreatDaneB.Yellow_@@lAbC.E*lk_HoundD.;Ridge-Back18. 如何为文件bar建符号链接foo?A. ln -s bar fooB. ls -f bar fooC. ln -f foo barD. ls -l bar foo19.在windows系统中如何通过命令行更改ip地址?A.ifconfigB.ipconfigshD.route20.在AIX文件系统中lost+found目录有()作用?A.JFS文件系统日志需要B.作为文件系统的垃圾箱C.允许fsck恢复孤儿文件和目录D.被删除文件的临时存储区21.在UNIX系统中,通过以下什么命令能获取UNIX命令的在线帮助?A.help <command>B.man <command>C.ls <command>D.show <command>22. 环境变量PS1的作用是:A. 使用彩色显示信息B. 改变命令提示符的外观C. 改变终端的参数D. 改变第二提示符的外观23. 下面哪个Linux命令可以一次显示一页内容?A. pauseB. catC. moreD.pg24. 怎样更改一个文件的权限设置?A. attribB. chmodC. changeD. file25. 在AIX系统中,文件集的版本号为:“5.1.25.6”,那么其中对“25”描述正确的是?A. Modification号B. Release号C. Version号D. Fix号26.在windows系统中,通过以下命令对文件系统进行转换。
多功能Windows命令提示符的使用方法一、Windows命令提示符的基础知识Windows命令提示符是Windows操作系统中的一种命令行工具,也被称为CMD。
通过CMD,用户可以在交互式的环境中使用命令行来完成一系列操作,如文件管理、网络设置等。
本章将介绍Windows命令提示符的安装和启动方式。
1.1 安装Windows命令提示符Windows操作系统自带了CMD,因此不需要额外安装。
用户只需按下Win+R组合键,弹出"运行"对话框,输入"cmd"后按下回车键即可打开命令提示符。
1.2 启动Windows命令提示符除了通过运行对话框打开CMD,还可以通过以下方式启动CMD:- 通过开始菜单:打开"开始"菜单,在搜索框中输入"cmd",点击提示符图标即可启动CMD。
- 通过快捷键:按下Win+X组合键,选择"命令提示符"或"Windows PowerShell"即可启动CMD。
二、Windows命令提示符的常用命令Windows命令提示符提供了丰富的命令,用于执行不同的任务。
本章将介绍一些常用的Windows命令。
2.1 文件管理命令2.1.1 dir:显示当前目录中的文件和子目录。
2.1.2 cd:切换当前目录。
2.1.3 mkdir:创建新目录。
2.1.4 copy:复制文件或目录。
2.1.5 del:删除文件。
2.1.6 move:移动文件或目录。
2.2 系统管理命令2.2.1 tasklist:列出当前正在运行的进程。
2.2.2 taskkill:终止指定进程。
2.2.3 systeminfo:显示系统信息。
2.2.4 netstat:显示网络连接状态。
2.2.5 ipconfig:显示网络配置信息。
2.3 网络命令2.3.1 ping:测试网络连接。
2.3.2 tracert:跟踪数据包在网络中的路径。
Windows使用命令重定向操作符(Redirection Operators)可以使用重定向操作符将命令输入和输出数据流从默认位置重定向到不同的位置。
输入或输出数据流的位置即为句柄。
下表列出了可用于将命令输入和输出数据流进行重定向的操作符。
重定向操作符说明>将命令输出写入到文件或设备(例如打印机)中,而不是写在命令提示符窗口中。
<从文件中而不是从键盘中读入命令输入。
>>将命令输出添加到文件末尾而不删除文件中的信息。
>&将一个句柄的输出写入到另一个句柄的输入中。
<&从一个句柄读取输入并将其写入到另一个句柄输出中。
|从一个命令中读取输出并将其写入另一个命令的输入中。
也称作管道。
默认情况下,可以从键盘将命令输入(即 STDIN 句柄)发送到 Cmd.exe,然后由 Cmd.exe 将命令输出(即 STDOUT 句柄)发送到命令提示符窗口。
一般的命令行程序输入输出请求都通过内部定义三个“端口”(在NT下称为“句柄”,在DOS下未定义)来完成,分别为标准输入stdin、标准输出stdout、标准错误stderr。
它们通常指向的设备为控制台(console,代码为CON),其中stdin指向控制台的键盘,stdout/stderr指向控制台的监视器。
因此,控制台通常即指键盘与监视器的联合体,这是在早期大型机的终端机上所体现出来的概念。
其中的stdin可被<重定向,stdout可被>、>>重定向,而stderr在DOS 下不可直接重定向,只有通过ctty或其它命令将系统控制权转交给其它设备的方式,来间接完成。
下表将列出可用的句柄。
句柄句柄的数字代号说明STDIN 0 键盘输入STDOUT 1 输出到命令提示符窗口STDERR 2 错误输出到命令提示符窗口UNDEFINED 3-9 这些句柄由应用程序和各个具体工具单独定义。
数字 0 到 9 代表前 10 个句柄。
高效管理Windows CMD命令输出结果的技巧Windows CMD命令是系统管理员和开发人员必备的工具之一。
通过CMD命令,我们可以执行各种系统管理任务和自动化脚本。
然而,CMD命令的输出结果通常很难阅读和理解。
在本文中,我将分享一些高效管理Windows CMD命令输出结果的技巧,帮助您更好地利用这个强大的工具。
1. 使用管道符号(|)过滤输出CMD命令的输出通常包含大量信息,但我们只对其中的一部分感兴趣。
使用管道符号(|)可以将命令的输出传递给另一个命令进行过滤。
例如,如果我们只想查看某个目录下的文件列表,可以使用"dir | findstr .txt"命令,它会将dir命令的输出结果传递给findstr命令进行过滤,只显示包含".txt"的文件。
2. 使用重定向符号(>)将输出保存到文件有时候,我们需要将CMD命令的输出结果保存到文件中进行后续处理。
使用重定向符号(>)可以将命令的输出重定向到文件中。
例如,"ipconfig >network_info.txt"命令会将ipconfig命令的输出结果保存到名为network_info.txt的文件中。
3. 使用通配符(*)进行模糊匹配CMD命令支持通配符(*)进行模糊匹配。
通过在命令中使用通配符,我们可以更快速地找到我们感兴趣的内容。
例如,"dir *.doc"命令会列出当前目录下所有扩展名为.doc的文件。
4. 使用命令行参数控制输出格式许多CMD命令提供了命令行参数,用于控制输出的格式。
通过使用这些参数,我们可以根据自己的需求来定制输出结果。
例如,"tasklist /FO TABLE"命令会以表格形式显示当前运行的进程列表。
5. 使用快捷键和命令历史CMD命令支持许多快捷键和命令历史功能,可以提高我们的工作效率。
例如,按下上箭头键可以回顾之前执行过的命令,按下Tab键可以自动补全命令或文件名。
.bat 重定向用法-回复“重定向”是一种在命令行界面下使用的功能,可以将命令的输出结果发送至指定位置,而不是在屏幕上显示。
在Windows操作系统中,批处理脚本(.bat)是一种常见的脚本语言,可以用于自动化任务和批量处理。
本文将详细介绍在批处理脚本中使用重定向的用法,为读者提供一步一步的解释和示例。
第一部分:什么是重定向?重定向是一种重要的命令行功能,可将命令的输出结果发送到不同的位置,而不是在屏幕上显示。
在批处理脚本中,重定向可以用于将命令的输出结果保存到文件中,或者将其作为另一个命令的输入。
常用的重定向操作符有两种:标准输出重定向和标准错误重定向。
第二部分:标准输出重定向标准输出重定向主要用于将命令的输出结果保存到文件中。
在批处理脚本中,可以使用大于符号(>)来进行标准输出重定向。
下面是一个示例:echo Hello, World! > output.txt上述命令将“Hello, World!”保存到名为“output.txt”的文件中。
如果文件已经存在,命令将覆盖现有内容;如果文件不存在,命令将创建新文件并写入内容。
如果你希望将输出结果追加到文件末尾而不是覆盖原有内容,可以使用双大于符号(>>)。
示例如下:echo New line! >> output.txt上述命令将“New line!”追加到“output.txt”文件末尾。
第三部分:标准错误重定向与标准输出重定向类似,标准错误重定向用于将命令的错误消息保存到文件中。
在批处理脚本中,可以使用2>操作符进行标准错误重定向。
示例如下:dir NonExistingFolder 2> error.txt上述命令将搜索名为“NonExistingFolder”的文件夹,如果该文件夹不存在,则错误消息将保存到“error.txt”文件中。
需要注意的是,如果希望同时重定向标准输出和标准错误,可以使用&操作符。
Windows CMD命令的高级输入输出重定向技巧在Windows操作系统中,CMD命令是一种非常常用的工具,它可以帮助我们进行各种操作和管理任务。
除了基本的命令行操作外,CMD还提供了一些高级的输入输出重定向技巧,可以帮助我们更加灵活地处理命令行的输入和输出。
本文将介绍一些常用的高级输入输出重定向技巧,帮助读者更好地利用CMD命令。
1. 输入重定向输入重定向是指将文件中的内容作为命令的输入。
在CMD命令中,我们可以使用"<"符号来实现输入重定向。
例如,我们可以将一个文本文件的内容作为命令的输入,如下所示:```命令 < 文件名```这样,CMD命令会将文件中的内容作为命令的输入,从而实现对文件内容的处理。
这在处理大量数据或者批量处理任务时非常有用。
2. 输出重定向输出重定向是指将命令的输出结果保存到文件中。
在CMD命令中,我们可以使用">"符号来实现输出重定向。
例如,我们可以将命令的输出结果保存到一个文本文件中,如下所示:```命令 > 文件名```这样,CMD命令会将输出结果保存到指定的文件中,而不是在命令行窗口中显示。
这对于需要保存命令输出结果的情况非常有用,可以方便后续的查看和分析。
3. 追加输出有时候,我们可能需要将命令的输出结果追加到一个已存在的文件中,而不是覆盖原有文件。
在CMD命令中,我们可以使用">>"符号来实现追加输出。
例如,我们可以将命令的输出结果追加到一个已存在的文本文件中,如下所示:```命令 >> 文件名```这样,CMD命令会将输出结果追加到指定的文件中,而不会覆盖原有文件内容。
这对于需要将多次命令输出结果保存到同一个文件中的情况非常有用。
4. 错误输出重定向在CMD命令中,除了标准输出外,还有一种称为错误输出的输出流。
错误输出通常用于显示命令执行过程中的错误信息。
Windows CMD命令中的管道和重定向技巧在Windows操作系统中,CMD命令是一种非常常见和实用的工具。
它可以帮助我们完成各种任务,如文件操作、系统管理和网络配置等。
其中,管道和重定向是CMD命令中非常重要的技巧,它们可以提高我们的工作效率和操作便利性。
本文将介绍CMD命令中的管道和重定向技巧,并提供一些实用的示例。
一、管道技巧管道是CMD命令中的一种特殊符号,用于将一个命令的输出作为另一个命令的输入。
通过使用管道,我们可以将多个命令串联起来,实现更复杂的操作。
下面是一些常见的管道技巧:1. 使用管道符号“|”将两个命令连接起来。
例如,我们可以使用“dir | findstr .txt”命令来查找当前目录下的所有txt文件。
2. 通过管道将命令的输出导出到文件中。
例如,我们可以使用“dir > file.txt”命令将当前目录下的文件列表导出到名为file.txt的文件中。
3. 使用管道将命令的输出作为另一个命令的输入。
例如,我们可以使用“type file.txt | findstr keyword”命令在file.txt文件中查找包含关键字的行。
二、重定向技巧重定向是CMD命令中的另一种重要技巧,它可以将命令的输入或输出重定向到文件或设备中。
通过使用重定向,我们可以更灵活地处理命令的输入和输出。
下面是一些常见的重定向技巧:1. 使用重定向符号“>”将命令的输出重定向到文件中。
例如,我们可以使用“dir > file.txt”命令将当前目录下的文件列表重定向到名为file.txt的文件中。
2. 使用重定向符号“>>”将命令的输出追加到文件中。
例如,我们可以使用“echo text >> file.txt”命令将文本追加到file.txt文件的末尾。
3. 使用重定向符号“<”将文件的内容作为命令的输入。
例如,我们可以使用“findstr keyword < file.txt”命令在file.txt文件中查找包含关键字的行。
Windows进程内标准输出重定向及其在程序调试上的应用
一、如何实现
打印调试信息的方法有很多,最常用的是使用标准输出设备(如printf、cout等),也可以用OutPutDebugString输出、用DebugView工具查看,还可以写入日志文件。
如果程序运行需要记录日志(log),往往需要打开个文件,或许是写入系统事件、用系统的事件查看器查看。
应用程序打印调试信息、日志的方法往往是确定的,但如果是要编写一个模块或者说组件,那样的输出信息应该写入哪里呢?或者说程序本身对此也没有明确需求的话,那该怎么办呢?
可喜的是一个进程的标准输出是可以重定向的,所以我建议把调试信息直接打到标准输出上,这样代码中可以统一使用cout或者printf,然后根据需要将标准输出重定向。
Linux中重定向标准输出就容易了,因为有强大的dup2函数。
而对于Windows的重定向,貌似往往是用于子进程的,在用CreateProcess创建子进程时设置子进程的标准输出句柄。
而我们想要的是重定向自己这个进程的标准输出,那个用不上。
我在MSDN中也没找到类似dup2的Win32 API函数,只有一个DuplicateHandle函数,这相当于linux中的dup,也用不上。
这里顺便提下,SetStdHandle是不能实现重定向的。
这个函数的功能是将某句柄指向标准设备,并不能将标准设备句柄重定向到另外的句柄。
于是我就想到,Windows不是支持一部分POSIX标准的吗。
于是我找到了一个CRT的函数,叫_dup2,看起来是不是特眼熟,对了,这就是Windows中dup2的兼容版本。
值得注意的是,_dup2以及与此相关的一系列CRT中的IO函数(如_read,_write)均以下划线开头,其余与linux大致相同,其参数中所谓的文件描述符与Win32中的句柄不一样,文件描述符实际上是句柄数组的索引,也就是说文件描述符不能与句柄混用。
比如0,1,2分别是标准输入、标准输出、标准错误的文件描述符,但句柄值不是这样确定的。
文件描述符不是Win32的概念,是POSIX中的概念。
_dup2用法与dup2大致相同,不多解释,不了解的可以查阅dup2相关资料。
下面讲点应用。
二、如何应用于调试
写一个模块时,我们可以直接用cout/printf来作调试。
但是如果这个模块用于图形界面或许是系统服务呢?这时标准输出看不到了,我们可以用OutPutDebugString函数和DebugView 这样的调试工具。
这样就带来一种选择,而选择往往是增加软件复杂度的因素。
所以我的想法是代码中只用cout/printf,如果需要将其重定向到调试工具中去。
如何实现呢,用匿名管道和线程。
用一个pipe,标准输出重定向到其write端,然后创建一个线程,线程要做的就是从pipe的
read端读出数据后用OutPutDebugString输出。
下面是实现代码。
头文件是这样子的,构造时重定向,析构时解除:
namespace common {
// 将标准输出重定向到DebugView,保持对象存在即有效
class StdoutToDebugString {
public:
StdoutToDebugString();
~StdoutToDebugString();
private:
int fds_[2];
int orign_stdout_;
uintptr_t thread_handle_;
};
}
实现文件:
#include<io.h>
#include<fcntl.h>
#include<stdio.h>
#include<process.h>
#include<Windows.h>
#include"StdoutRedirect.h"
using namespace common;
const int kBufferSize = 4096;
unsigned__stdcall RedirectThreadProc(void* param) { int pipe_read = (int)param;
char buf[kBufferSize];
int bytes_read;
do {
bytes_read = ::_read(pipe_read, buf, kBufferSize);
buf[bytes_read] = 0;
::OutputDebugString(buf);
} while (bytes_read);
return 0;
};
StdoutToDebugString::StdoutToDebugString() {
::_pipe(fds_, kBufferSize, _O_TEXT);
orign_stdout_ = _dup(_fileno(stdout));
::_dup2(fds_[1], _fileno(stdout));
thread_handle_= ::_beginthreadex(NULL, 0, RedirectThreadProc, (void*)fds_[0], 0, NULL);
::CloseHandle((HANDLE)thread_handle_);
}
StdoutToDebugString::~StdoutToDebugString() {
::_dup2(orign_stdout_, _fileno(stdout));
}
测试代码:
#include<iostream>
#include<Windows.h>
#include"../Common/StdoutRedirect.h"
using namespace std;
using namespace common;
void main() {
StdoutToDebugString redirect;
cout << "hello" << endl;
::system("pause");
}
运行时可以看到控制台上并没有打印出hello,而在DebugView中可以看到。
三、未解决的问题?
因为_read是阻塞的,我没有办法能安全地结束掉那个线程,所以我无法在析构时等待线程结束。
这样如果对象已经析构而线程依然在跑,_read会引发assert导致崩溃。
不过在一般情况下,在main的开始构造这样一个对象来实现重定向,一直维持到main结束,是没有问题的。
对于此问题,还望牛人指点。