重定位本进程的标准输出至文件(非子进程)

环境:Win7、VC6

1、

代码:

 1 #include <windows.h>
 2 #include <stdio.h>
 3
 4 #include <io.h>
 5 #include <Fcntl.h>
 6
 7 int main()
 8 {
 9     printf("Sub01 : *stdin : %x\n", *stdin);
10     printf("Sub01 : *stdout : %x\n", *stdout);
11     printf("Sub01 : *stderr : %x\n", *stderr);
12     printf("\n");
13
14     printf("Sub01 : GetStdHandle(STD_INPUT_HANDLE) return : %x\n", GetStdHandle(STD_INPUT_HANDLE));
15     printf("Sub01 : GetStdHandle(STD_OUTPUT_HANDLE) return : %x\n", GetStdHandle(STD_OUTPUT_HANDLE));
16     printf("Sub01 : GetStdHandle(STD_ERROR_HANDLE) return : %x\n", GetStdHandle(STD_ERROR_HANDLE));
17
18 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
19     // 创建 文件
20
21     HANDLE hFile = CreateFile("C:\\ZXC_20151109.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
22     if (hFile == INVALID_HANDLE_VALUE)
23     {
24         printf("Could not open file (error %d)/n", GetLastError());
25         return 0;
26     }
27
28     // 从句柄,得到 文件描述符(File Description)
29     int fd = _open_osfhandle((long)hFile, _O_TEXT);
30     // 由 fd 创建流
31     FILE* fp = _fdopen( fd, "w+" );
32     // 更改 标准输出流
33     *stdout = *fp;
34
35     printf("Sub01 : *stdin : %x\n", *stdin);
36     printf("Sub01 : *stdout : %x\n", *stdout);
37     printf("Sub01 : *stderr : %x\n", *stderr);
38     printf("\n");
39
40     printf("Sub01 : GetStdHandle(STD_INPUT_HANDLE) return : %x\n", GetStdHandle(STD_INPUT_HANDLE));
41     printf("Sub01 : GetStdHandle(STD_OUTPUT_HANDLE) return : %x\n", GetStdHandle(STD_OUTPUT_HANDLE));
42     printf("Sub01 : GetStdHandle(STD_ERROR_HANDLE) return : %x\n", GetStdHandle(STD_ERROR_HANDLE));
43
44     return 0;
45 }

控制台输出:

1 Sub01 : *stdin : 428600
2 Sub01 : *stdout : 0
3 Sub01 : *stderr : 0
4
5 Sub01 : GetStdHandle(STD_INPUT_HANDLE) return : 3
6 Sub01 : GetStdHandle(STD_OUTPUT_HANDLE) return : 7
7 Sub01 : GetStdHandle(STD_ERROR_HANDLE) return : b
8 Press any key to continue

文件ZXC_20151109.txt中的输出:

1 Sub01 : *stdin : 428600
2 Sub01 : *stdout : 293d20
3 Sub01 : *stderr : 0
4
5 Sub01 : GetStdHandle(STD_INPUT_HANDLE) return : 3
6 Sub01 : GetStdHandle(STD_OUTPUT_HANDLE) return : 7
7 Sub01 : GetStdHandle(STD_ERROR_HANDLE) return : b

PS:由 文件描述符(fd:File Description) 得到 对应的文件句柄(file handle)(HANDLE) : “long = _get_osfhandle(int fd);”。

PS:网页资料:(http://demon.tw/programming/_get_osfhandle.html)

_get_osfhandle函数可以获取文件描述符(file descriptor)对应的文件句柄(file handle)。

众所周知,系统中stdin、stdout、stderr的文件描述符分别是0、1、2,所以可以用_get_osfhandle函数来获取它们的句柄。

#include <io.h>
#include <tchar.h>
#include <windows.h>

int main()
{
    LPTSTR s = TEXT("http://demon.tw\n");
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE _hStdOut = (HANDLE) _get_osfhandle(1);
    if (hStdOut == _hStdOut) {
        WriteConsole(hStdOut, s, lstrlen(s), NULL, NULL);
    }
    return 0;
}

可以看到,_get_osfhandle的返回值和GetStdHandle取得的标准输出句柄是一样的。

我的测试代码:

 1 #include <windows.h>
 2 #include <stdio.h>
 3
 4 #include <io.h>
 5 #include <Fcntl.h>
 6
 7 int main()
 8 {
 9     char* s = "http://demon.tw\n";
10     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
11     HANDLE _hStdOut = (HANDLE) _get_osfhandle(1);
12     if (hStdOut == _hStdOut) {
13         WriteConsole(hStdOut, s, lstrlen(s), NULL, NULL);
14     }
15
16     printf("_hStdOut : %x , GetStdHandle(STD_OUTPUT_HANDLE) : %x\n", _hStdOut, hStdOut);
17     return 0;
18 }

控制台的输出:

http://demon.tw
_hStdOut : 7 , GetStdHandle(STD_OUTPUT_HANDLE) : 7
Press any key to continue

Z

时间: 2024-11-03 21:02:51

重定位本进程的标准输出至文件(非子进程)的相关文章

重定位本进程的标准输出(非子进程)

PS:标准输入/标准错误 ,参考这个来弄吧. 环境:Win7(32位/64位),VC6 1. printf("*stdin : %x\n", *stdin); printf("*stdout : %x\n", *stdout); printf("*stderr : %x\n", *stderr); printf("stdin : %x\n", stdin); printf("stdout : %x\n",

PE文件结构(五)基址重定位

PE文件结构(五) 参考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 基址重定位 链接器生成一个PE文件时,它会假设程序被装入时使用的默认ImageBase基地址(VC默认exe基地址00400000h,dll基地址10000000h),并且会把代码中所有指令中用到的地址都使用默认的基地址(例如 程序代码中 push 10001000,就是把10000000h当做了基地址,把push 10001000写入到文件中).如果一个exe程序中一个dll装载时的地址与其它dll地址发生冲突(因为

可重定位目标文件

[0]GCC将源代码转化成可执行代码的流程 (1)C预处理器cpp扩展源代码,插入所有用#include命令指定的文件,并扩展声明的宏: (2)编译器ccl产生两个源代码的汇编代码:*.s: (3)汇编器as将汇编代码转化为二进制目标代码 :*.o ; (目标代码是机器代码的一种形式,它包含所有指令的二进制表示,但没有填入地址的全局值) (4)链接器ld将目标代码与实现库函数的代码合并,最终产生可执行代码文件: [1]第一步,源码演说 [2]生成目标文件p107.o 及对其反汇编 2.1) gc

重定位和链接脚本

大部分指令是"位置有关编码" 位置无关编码:汇编源文件编码成二进制可执行程序时,编码方式与位置无关. 在我们写程序时,必须给编译器链接器指定地址.将来的程序被执行时必须放在当时编译链接时给定的地址才能运行. 位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关的. 但是也有一种特别的指令他可以跟指定的链接地址没有关系,这些代码不管放在哪里都可以正常运行. 分析: 之前的裸机程序中,makefile中用-Ttext 0x0来指定链接地址是0x0;这意味着我们认为将来这个程序会被

关于C++中的重定位

"标准库定义了4个IO对象,处理输入时使用命名为cin的istream类型对象,这个对象也成为标准输入.处理输出时使用命名为cout的ostream类型对象,这个对象也称为标准输出.标准库还定义了另外两个ostream对象,分别命名为cerr和clog.cerr对象又叫标准错误,通常用来输出警告和错误信息给程序的使用者,而clog对象用于产生程序执行的一般信息.一般情况下,系统将这些对象与执行窗口联系起来,这样,当我们从cin读入时,数据从执行程序的窗口读入,当写到cout.cerr.clog时

Tiny6410之重定位代码到SRAM+6096

重定位代码 两个不同的地址概念: 对于程序而言,需要理解两个地址,一个是程序当前所处的地址,即程序运行时所处的当前地址.二是程序应该位于的运行地址,即编译程序时所指定的程序的链接地址.在Tiny6410中板子上电启动时只会从NAND Flash/MMC等启动设备中拷贝前8K的代码到SRAM中,然后跳转到SRAM中运行代码.那么问题就来了,如果我们的程序超过8K会出现什么问题呢?程序拷贝不完整运行当然出错.所以就需要我们在前8K的代码中实现将整个程序完整的拷贝到DRAM等其他更大的存储空间,然后在

重定位与链接脚本

1.为什么需要重定位 位置无关编码(PIC,position independent code):汇编源文件被编码成二进制可执行程序时编码方式与位置(内存地址)无关. 位置有关编码:汇编源码编码成二进制可执行程序后和内存地址是有关的. 我们在设计一个程序时,会给这个程序指定一个运行地址(链接地址).就是说我们在编译程序时其实心里是知道我们程序将来被运行时的地址(运行地址)的,而且必须给编译器链接器指定这个地址(链接地址)才行.最后得到的二进制程序理论上是和你指定的运行地址有关的,将来这个程序被执

程序地址重定位和模块绑定

1.程序的构建 在构建程序的时候,链接器都会给程序设置一个默认的加载地址,即首选基地址,它表示该模块被映射到进程地址空间时最佳的内存地址.默认情况下,对于EXE程序而言,windows链接器会将它的首选基地址设置为0X400000(四十万),而DLL程序的首选基地址则被设置为0X10000000(1千万),然后链接器将该地址以及一些相关数据和代码的地址写入到PE文件中.首选基地址的是为了系统程序加载器设计的,作用是告诉加载器把程序优选加载到该首选基地址,然后就可以直接将其他的数据和代码加载到内存

共享库加载时重定位

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries 本文的目的是解释现代操作系统怎样使得共享库加载时重定位成为可能.它关注执行在32位x86的LinuxOS.但通用的原则也适用于其它OS与CPU. 共享库有很多名字--共享库,共享对象,动态共享对象(DSO),动态链接库(DLL--假设你有Windows背景).为了统一起见.我将尽量在本文里使用"共享库