AttachConsole和64位应用程序

时间:2019-04-17 11:08:34

标签: delphi winapi

当程序编译为64位时,WinAPI函数AttachConsole始终返回true。

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

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

然后我调用我的函数:

if AttachConsole(DWORD(-1)) then
   ....

当编译为32位应用程序时,此方法工作正常,但当编译为64位应用程序时,它始终返回true。

documentation并未提及对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也会重新运行。

1 个答案:

答案 0 :(得分:9)

通过documenation链接,dwProcessId [in]可以采用两种类型的值-目标进程的PID或特殊参数:

  

ATTACH_PARENT_PROCESS (DWORD)-1

     

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

此处您使用的是值ATTACH_PARENT_PROCESS

在进行64位调试的情况下,IDE似乎正在为64位调试器创建一个控制台,该控制台将调试后的应用程序作为子项承载,因此选择附加到父控制台会成功。

对于32位调试会话,该应用程序作为IDE的子级产生。我们可以猜测这是因为IDE本身是一个32位应用程序,并且可以将64位应用程序必须附加到64位调试器上而直接挂接到32位进程中。

使用流程浏览器,我们可以在IDE中启动调试流程时看到流程层次结构的差异:

enter image description here

enter image description here

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

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