C# API函数AllocConsole和AttachConsole(-1)之间有什么不同?
请您解释一下,API函数C# API函数AllocConsole和AttachConsole(-1)之间有什么不同?,c#,.net,winapi,console,C#,.net,Winapi,Console,请您解释一下,API函数AllocConsole和AttachConsole(-1)之间有什么不同?我的意思是,如果AttachConsole获取ATTACH\u PARENT\u PROCESS(DWORD)-1我已经有一段时间没有使用winapi了,但是我查找了,却找不到CreateConsole API函数。所以我猜CreateConsole是遗留的东西,已经被AttachConsole取代。所以可能没有什么不同,但是CreateConsole可能已经被弃用了。我认为没有一个函数叫做Cre
AllocConsole
和AttachConsole(-1)
之间有什么不同?我的意思是,如果AttachConsole
获取ATTACH\u PARENT\u PROCESS(DWORD)-1
我已经有一段时间没有使用winapi了,但是我查找了,却找不到CreateConsole API函数。所以我猜CreateConsole是遗留的东西,已经被AttachConsole取代。所以可能没有什么不同,但是CreateConsole可能已经被弃用了。我认为没有一个函数叫做CreateConsole
,但是有一个
假设这就是你的意思,我认为区别在于如果父进程没有控制台,AttachConsole(ATTACH\u PARENT\u PROCESS)
可以
尝试从命令提示符和Start->Run运行此代码:
#include <windows.h>
#pragma comment ( lib, "user32.lib" )
int main()
{
BOOL b;
char msg[1024];
b = FreeConsole();
sprintf(msg, "%d", b);
MessageBox(NULL, msg, "FreeConsole", 0);
b = AttachConsole(ATTACH_PARENT_PROCESS);
sprintf(msg, "%d", b);
MessageBox(NULL, msg, "AttachConsole", 0);
return 0;
}
#包括
#pragma注释(lib,“user32.lib”)
int main()
{
布尔b;
char-msg[1024];
b=自由控制台();
sprintf(msg,“%d”,b);
MessageBox(空,消息,“FreeConsole”,0);
b=附加控制台(附加父进程);
sprintf(msg,“%d”,b);
MessageBox(空,消息,“AttachConsole”,0);
返回0;
}
在命令提示符下运行时,将显示两个包含
1
的消息框,这意味着两个调用都成功。从开始->运行运行时,第一个框包含1
,第二个框包含0
,这意味着只有第一次调用成功。第二个失败是因为explorer.exe(它是从Start->Run启动的进程的父进程)没有控制台。好吧,基本区别是:
将创建一个新控制台(并连接到它)alloconsole()
不会创建新控制台,它将附加到父进程的现有控制台AttachConsole(ATTACH\u PARENT\u PROCESS/*-1*/)
int main( int argc, char* argv[])
{
int ch;
BOOL bResult;
printf( "default console\n");
ch = getchar();
bResult = FreeConsole();
bResult = AllocConsole();
printf( "AllocConsole()\n");
ch = getchar();
bResult = FreeConsole();
bResult = AttachConsole( ATTACH_PARENT_PROCESS);
printf( "AttachConsole( ATTACH_PARENT_PROCESS)\n");
ch = getchar();
return 0;
}
在Windows 7上,当您执行
cmd.exe
时,CreateProcess
将具有CREATE\u NEW\u CONSOLE
标志,该标志将分配一个新控制台,而不是附加到父控制台(当PE头包含Subsystem=3
时,这是默认行为,即IMAGE\u Subsystem\u WINDOWS\u CUI
表示它是控制台应用程序)。这意味着将在当前进程地址空间中的.exe
图像入口点之前调用alloconsole
alloconsole
创建一个新的conhost.exe
实例,该实例绘制GUI窗口,处理鼠标和键盘事件,维护和写入输入缓冲区,维护和读取屏幕缓冲区,当出现键盘事件时,更新输入缓冲区。alloconsole
还设置cmd.exe
中的ParameterBlock
中的ode>stdin句柄将PEB处理到控制台输入缓冲区,将stdout
和stderr
处理到控制台伪句柄,并将ParameterBlock中的consoleehandle
设置为它所连接的
conhost.exe`实例的PID。
cmd.exe
是一个用C编写的控制台应用程序,如diskpart.exe
或setx.exe
,它向屏幕缓冲区显示命令提示符(cmd.exe
的stdout)从cmd.exe
的stdin
读取命令,解释要显示到stdout
的按键事件,并确定要调用的命令以及显示到stdout
的命令(可能是PEB中句柄中的文件,而不是发送到conhost
).命令本身有一个空的stdin
、匿名管道的读取端、文件或con
文件
cmd.exe
调用类似WriteFile
的函数,如果写入标准句柄(否则调用NtWriteFile
),该函数将调用writeconole
(它是writeconolea
的别名)。这将启动对ParameterBlock->ConsoleHandle
中的conhost.exe
PID的ALPC调用,传递控制台伪句柄和要将结果写入的缓冲区(或要读取的缓冲区)
当您从cmd.exe
内部执行cmd/c
时,它会创建一个子cmd.exe
,但不提供CREATE\u NEW\u CONSOLE
,这会导致子cmd.exe
附加到同一可见控制台,即conhost.exe
实例,并在entr之前调用AttachConsole
y点。使用admin/c
(admin版本的cmd.exe
)创建的子项不是这种情况如果在非提升的cmd.exe
中执行,则需要有一个新的conhost.exe
实例,因为它具有不同的权限。类似地,启动程序时,start
提供CREATE\u new\u控制台
,该控制台为其子进程打开一个新的conhost.exe
,但调用
并指定程序文件名+扩展名作为原始命令,不会打开另一个控制台窗口,而是附加到父级。cmd/c diskpart
创建一个子级cmd.exe
附加到父级所附加到的控制台,并