Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# API函数AllocConsole和AttachConsole(-1)之间有什么不同?_C#_.net_Winapi_Console - Fatal编程技术网

C# API函数AllocConsole和AttachConsole(-1)之间有什么不同?

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

请您解释一下,API函数
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*/)
    不会创建新控制台,它将附加到父进程的现有控制台
在第一种情况下,您将获得一个全新的控制台窗口,在第二种情况下,您将使用现有的控制台窗口

当然,如果您已经连接到控制台(即,您是从cmd.exe启动的控制台模式程序),则没有太大区别-您将在任何一个API中得到一个错误

还请注意,仅仅因为您从控制台分离并不意味着分离的控制台将是有用的-例如,如果您是从cmd窗口启动的控制台进程,则该窗口实际上会阻塞,直到进程结束

要使用的一些代码:

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
附加到父级所附加到的控制台,并