Mic*_*urr 13
那么,根本区别在于:
AllocConsole() 将创建一个新的控制台(并附加到它)AttachConsole( ATTACH_PARENT_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;
}
Run Code Online (Sandbox Code Playgroud)
我不认为有一个叫做的功能CreateConsole,但是有AllocConsole.
假设这就是你的意思,我认为不同之处在于,如果父进程没有控制台,则AttachConsole(ATTACH_PARENT_PROCESS)可以返回ERROR_INVALID_HANDLE.
尝试从命令提示符和开始 - >运行运行此代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
从命令提示符运行时,1将显示包含a的两个消息框,这意味着两个调用都成功.从"开始" - >"运行"运行时,第一个框包含1,第二个包含0,表示只有第一个调用成功.第二个失败是因为explorer.exe(从Start - > Run启动的进程的父进程)没有控制台.
在 Windows 7 上,当您执行 时cmd.exe,CreateProcess将具有该CREATE_NEW_CONSOLE标志,该标志将分配一个新控制台,而不是附加到父控制台(这是当 PE 头包含Subsystem = 3ie时的默认行为IMAGE_SUBSYSTEM_WINDOWS_CUI,表明它是一个控制台应用程序)。这意味着将在当前进程地址空间中的图像入口点AllocConsole之前调用。.exe
AllocConsole创建一个新conhost.exe实例,它绘制 GUI 窗口,处理鼠标和键盘事件,维护和写入输入缓冲区,维护和读取屏幕缓冲区,当有键盘事件时,它更新输入缓冲区。还将进程PEB中的句柄AllocConsole设置为控制台输入缓冲区和控制台伪句柄,并设置其附加到的ParameterBlock conhost.exe` 实例中。stdinParameterBlockcmd.exestdoutstderrConsoleHandleto the PID of the
cmd.exe是一个用 C 编写的控制台应用程序,类似于diskpart.exe或setx.exe,它将命令提示符显示到屏幕缓冲区 ( stdoutof ) 并从ofcmd.exe读取命令,解释要显示的按键事件以及确定要调用的命令和要执行的命令结果显示为(可能是 PEB 句柄中的文件,但未发送到)。命令本身要么什么都没有,要么是匿名管道的读取端,要么是文件,要么是文件。stdin cmd.exestdoutstdoutconhoststdincon
cmd.exeWriteFile如果它正在写入标准句柄(否则它调用),则调用类似的函数WriteConsole(它是 的别名)。这将启动对PID in 的ALPC 调用,传递控制台伪句柄和要写入结果的缓冲区(或要从中读取的缓冲区)。WriteConsoleANtWriteFileconhost.exeParameterBlock->ConsoleHandle
cmd /c当您从内部执行时cmd.exe,它会创建一个 child cmd.exe,但不提供CREATE_NEW_CONSOLE,这会导致 childcmd.exe附加到同一个可见控制台即conhost.exe实例,并AttachConsole在入口点之前调用。如果在非提升的 中完成,则使用admin /c(管理版本的)创建的子项则不是这种情况,它需要有一个新实例,因为它具有不同的权限。类似地,启动程序时,Supply会为其子进程打开一个新进程,但将程序文件名 + 扩展名指定为原始命令不会打开另一个控制台窗口,而是附加到父进程。创建一个附加到父级所附加到的控制台的子级,然后该子级创建自己的子级,该子级附加到父级所附加到的控制台。cmd.execmd.execonhost.exestartCREATE_NEW_CONSOLEconhost.execallcmd /c diskpartcmd.exediskpart.exe
当您执行 GUI 应用程序时,它不会分配或附加到控制台。如果您AllocConsole在应用程序中使用,它将创建一个新的conhost.exe控制台窗口(该窗口可以被应用程序隐藏,即搅拌机具有window > toggle system console,它通过获取控制台窗口的句柄conhost.exe然后在其上使用 using ShowWindowwith来实现此目的),但会SW_HIDE不创建子进程,因为它是当前进程的控制台窗口,所以现在会有2个窗口。AttachConsole您还可以改为附加到属于 进程的控制台(使用) pid。AttachConsole(-1)附加到父级pid。这将使用conhost该进程所附加的。
AttachConsole如果您已经连接到控制台而没有使用,则不能FreeConsole,并且如果您使用创建进程,则无法AttachConsole连接到父级控制台DETACHED_PROCESS。CREATE_NO_WINDOW具有相同的效果,即DETACHED_PROCESS它不附加到控制台应用程序或为控制台应用程序分配控制台,但允许它附加到父控制台。
| 归档时间: |
|
| 查看次数: |
9467 次 |
| 最近记录: |