AttachConsole 和 64 位应用程序

6

当以64位编译程序时,WinAPI函数AttachConsole总是返回true。

首先,我声明了以下函数:

function AttachConsole(dwProcessId: DWORD): Bool; stdcall; external KERNEL32 name 'AttachConsole';

然后我调用我的函数:
if AttachConsole(DWORD(-1)) then
   ....

这段代码在32位应用程序编译时运行良好,但在64位编译时总是返回true。 文档没有提到需要为64位应用程序做特殊处理。
如何重现:
1.创建一个新的VCL应用程序
2.将目标平台设置为Win64
3.将DPR文件编辑为以下内容:

program Project1;

uses
  System.Types,
  WinApi.windows,
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

function AttachConsole(dwProcessId: DWORD): Bool; stdcall; external KERNEL32 name 'AttachConsole';


begin
  if AttachConsole(DWORD(-1)) then
  begin
    writeLN('Hello world');
    Exit;
  end;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

在Win64下运行时,即使从资源管理器中运行,AttachConsole也会返回true。

1
也许,64位编译器对DWORD(-1)有一些奇怪的处理方式 - 你尝试过使用$FFFFFFFF吗? - 500 - Internal Server Error
是的,相同的结果:假阳性。 - Jens Borrisholt
如果您附加二进制代码而不是源代码,那将更有用。 - RbMm
1个回答

9
文档链接中可以看到,dwProcessId [in]可以采用两种类型的值:目标进程的PID或特殊参数:

ATTACH_PARENT_PROCESS(DWORD)-1

使用当前进程父级的控制台。

在这里您正在使用值为ATTACH_PARENT_PROCESS的参数。

对于64位调试,IDE似乎正在创建一个控制台,用作调试应用程序的子级的64位调试器,并选择附加到父控制台成功。

对于32位调试会话,应用程序是IDE的子进程。我们可以猜测这是因为IDE本身是32位应用程序并且可以直接钩入32位进程,而64位应用程序必须附加到64位调试器。

使用进程资源管理器时,我们可以看到在IDE内启动进程以进行调试时进程层次结构的差异:

enter image description here

enter image description here

在这里,我们可以看到64位进程作为调试器内核中的子级托管,而32位进程则不是。

在调试器之外运行(64位)应用程序会产生预期结果,其中AttachConsole(ATTACH_PARENT_PROCESS)会失败。


抱歉,我的问题表述不清楚。你应该使用一个图形用户界面程序。我已经更新了问题。 - Jens Borrisholt
1
@JensBorrisholt 我已经更新了答案。我认为这就是发生的事情。 - J...
简而言之:当从调试器运行时,它在64位下无法工作。 - Jens Borrisholt
1
@JensBorrisholt 我想是这样,尽管“work”的含义不是很清楚——在64位调试中,将始终有一个可用于附加的父控制台。 如果你需要将这个特定的控制台与其他可能存在的父控制台区分开来,那当然是可能的。 - J...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接