问题描述
假设我们有两个可执行文件:
1.)ascii.exe产生ascii输出,即
Lets asume we have two executables:
1.) ascii.exe produces ascii output, i.e.
#include< stdio.h>
int main(){
printf("Hello World \ n");
返回0;
}
#include<stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
2.)utf16.exe产生utf16输出,即
2.) utf16.exe produces utf16 output, i.e.
#include< fcntl.h>
#include< io.h>
#include< stdio.h>
int main(){
_setmode(_fileno(stdout),_O_U16TEXT);
wprintf(L"Hello World \ n");
返回0;
}
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
int main() {
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"Hello World\n");
return 0;
}
"cmd.exe";支持ascii和utf16输出模式:可以通过
选择 "cmd.exe" -> ASCII模式
"cmd.exe/u"; -> unicode模式
两种模式之间的唯一区别是,在unicode模式下,所有输出均来自
"cmd.exe"本身(以及所有包含的工具,例如dir)将在utf16中,而在
中ascii模式下,所有"cmd.exe"输出将以ascii格式显示.
"cmd.exe" supports an ascii and an utf16 output mode: this can be selected by
"cmd.exe" -> ascii mode
"cmd.exe /u" -> unicode mode
The only difference between the two modes is that in unicode mode all output from
the "cmd.exe" itself (and all included tools like dir) will be in utf16, while in
ascii mode all output of "cmd.exe" will be in ascii.
我的两个示例可执行文件的输出始终相同,这意味着
"ascii.exe";总是产生ascii文字,
"utf16.exe";总是产生utf16文字.
The output from my two example executables is always the same, means
"ascii.exe" always produces ascii text and
"utf16.exe" always produces utf16 text.
我意识到"cmd.exe"正确显示输出,这意味着它(或
别人)知道"数据采用哪种编码方式.
I realise that "cmd.exe" correctly displays the output, meaning that it (or
someone else) "knows" what kind of encoding the data has.
现在,我启动"cmd.exe";使用CreateProcess从另一个C程序读取并读取其输出
在带有ReadFile的管道上.
我的目标是使用unicode作为默认编码,但是如果我启动诸如
"ascii.exe";我将收到ascii数据. (请找到附件程序.)
Now I start "cmd.exe" from another C program with CreateProcess and read its output
over a pipe with ReadFile.
My target is to use unicode as default encoding, but if I start a program such as
"ascii.exe" I will receive ascii data. (Please find attached program.)
问题是:如何获取有关接收到的数据的编码的信息
(不用猜测)?
当"cmd.exe"出现时,是否有可能得到通知?正在切换其输出编码?
The problem is: How can I get information about the encoding of the received data
(without guessing)?
Is it possible to get informed, when "cmd.exe" is switching its output encoding?
#include< windows.h>
#include< stdio.h>
#include< stdlib.h>
#include< string.h>
#include< fcntl.h>
#include< io.h>
#include< iostream>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
处理avg_stdin_write;
处理avg_stdout_read;
int main(){
SECURITY_ATTRIBUTES dsl_sec_attr; //管道安全属性
PROCESS_INFORMATION dsl_proc_info; //子进程信息
STARTUPINFO dsl_start_info; //子级开始信息
BOOL bol_ret; //返回几个func调用
处理 avl_stdin_read; //STDIN 阅读管道
处理 avl_stdout_write; //STDOUT写入管道
HANDLE avg_stdin_write;
HANDLE avg_stdout_read;
int main() {
SECURITY_ATTRIBUTES dsl_sec_attr; // pipe security attributes
PROCESS_INFORMATION dsl_proc_info; // child process info
STARTUPINFO dsl_start_info; // child start info
BOOL bol_ret; // return for several func calls
HANDLE avl_stdin_read; // STDIN read pipe
HANDLE avl_stdout_write; // STDOUT write pipe
//-------------------------------------------
//为输入和输出创建管道:
//-------------------------------------------
//设置安全属性:
dsl_sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
dsl_sec_attr.bInheritHandle = TRUE; //管道句柄是继承的
dsl_sec_attr.lpSecurityDescriptor = NULL;
//-------------------------------------------
// create pipes for in- and output:
//-------------------------------------------
// set security attributes:
dsl_sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
dsl_sec_attr.bInheritHandle = TRUE; // pipe handles are inherited
dsl_sec_attr.lpSecurityDescriptor = NULL;
//创建子STDOUT管道:
bol_ret = CreatePipe(& avg_stdout_read,& avl_stdout_write,& dsl_sec_attr,0);
if(bol_ret == FALSE){
printf("CreatePipe STDOUT管道失败\ n");
返回EXIT_FAILURE;
}
// create child STDOUT pipe:
bol_ret = CreatePipe( &avg_stdout_read, &avl_stdout_write, &dsl_sec_attr, 0 );
if ( bol_ret == FALSE ) {
printf( "CreatePipe STDOUT pipe failed\n" );
return EXIT_FAILURE;
}
//确保未继承STDOUT的管道的读取句柄
bol_ret = SetHandleInformation(avg_stdout_read,HANDLE_FLAG_INHERIT,0);
if(bol_ret == FALSE){
printf("SetHandleInformation STDOUT管道失败\ n");
返回EXIT_FAILURE;
}
// ensure the read handle to the pipe for STDOUT is not inherited
bol_ret = SetHandleInformation( avg_stdout_read, HANDLE_FLAG_INHERIT, 0 );
if ( bol_ret == FALSE ) {
printf( "SetHandleInformation STDOUT pipe failed\n" );
return EXIT_FAILURE;
}
//创建子STDIN管道:
bol_ret = CreatePipe(& avl_stdin_read,& avg_stdin_write,& dsl_sec_attr,0);
if(bol_ret == FALSE){
printf("CreatePipe STDIN管道失败\ n");
返回EXIT_FAILURE;
}
// create child STDIN pipe:
bol_ret = CreatePipe( &avl_stdin_read, &avg_stdin_write, &dsl_sec_attr, 0 );
if ( bol_ret == FALSE ) {
printf( "CreatePipe STDIN pipe failed\n" );
return EXIT_FAILURE;
}
//确保不继承STDIN管道的读取句柄
bol_ret = SetHandleInformation(avg_stdin_write,HANDLE_FLAG_INHERIT,0);
if(bol_ret == FALSE){
printf("SetHandleInformation STDIN管道失败\ n");
返回EXIT_FAILURE;
}
// ensure the read handle to the pipe for STDIN is not inherited
bol_ret = SetHandleInformation( avg_stdin_write, HANDLE_FLAG_INHERIT, 0 );
if ( bol_ret == FALSE ) {
printf( "SetHandleInformation STDIN pipe failed\n" );
return EXIT_FAILURE;
}
//-------------------------------------------
//创建子进程:
//-------------------------------------------
memset(& dsl_proc_info,0,sizeof(PROCESS_INFORMATION));
//-------------------------------------------
// create child process:
//-------------------------------------------
memset( &dsl_proc_info, 0, sizeof(PROCESS_INFORMATION) );
//指定用于重定向的STDIN和STDOUT句柄.
memset(& dsl_start_info,0,sizeof(STARTUPINFO));
dsl_start_info.cb = sizeof(STARTUPINFO);
dsl_start_info.hStdError = avl_stdout_write;
dsl_start_info.hStdOutput = avl_stdout_write;
dsl_start_info.hStdInput = avl_stdin_read;
dsl_start_info.dwFlags | = STARTF_USESTDHANDLES;
// specify the STDIN and STDOUT handles for redirection.
memset( &dsl_start_info, 0, sizeof(STARTUPINFO) );
dsl_start_info.cb = sizeof(STARTUPINFO);
dsl_start_info.hStdError = avl_stdout_write;
dsl_start_info.hStdOutput = avl_stdout_write;
dsl_start_info.hStdInput = avl_stdin_read;
dsl_start_info.dwFlags |= STARTF_USESTDHANDLES;
bol_ret = CreateProcess(NULL,
nbsp; bsp " cmd/u", //子进程
nbsp; bsp NULL, //处理安全性属性
nbsp; bsp NULL, //主线程安全属性
nbsp; bsp TRUE, //句柄是继承的
nbsp; bsp 0, //创建标志
nbsp; bsp NULL, //使用父母的环境
nbsp; bsp NULL, //使用父级的当前目录
nbsp; bsp & dsl_start_info, //STARTUPINFO指针
nbsp; bsp & dsl_proc_info ); //接收PROCESS_INFORMATION
if(bol_ret == FALSE){
printf("CreateProcess失败\ n");
返回EXIT_FAILURE;
}
bol_ret = CreateProcess( NULL,
"cmd /u", // child process
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&dsl_start_info, // STARTUPINFO pointer
&dsl_proc_info ); // receives PROCESS_INFORMATION
if ( bol_ret == FALSE ) {
printf( "CreateProcess failed\n" );
return EXIT_FAILURE;
}
//关闭未使用的管道:
CloseHandle(avl_stdout_write);
CloseHandle(avl_stdin_read );
// close unused pipes:
CloseHandle( avl_stdout_write );
CloseHandle( avl_stdin_read );
//-------------------------------------------
//与子进程通信:
//-------------------------------------------
//-------------------------------------------
// communicate with child process:
//-------------------------------------------
/*
...
...
...
*/
/*
...
...
...
*/
返回EXIT_SUCCESS;
}
return EXIT_SUCCESS;
}
推荐答案
我有兴趣学习该问题的其他解决方案.
I am interested to learn any other solution of this question.
这篇关于cmd.exe的Unicode问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!