【问题标题】:AttachConsole and 64 bit applicationAttachConsole 和 64 位应用程序
【发布时间】:2019-04-17 11:08:34
【问题描述】:

当程序编译为 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 即使在资源管理器中运行也会返回 true。

【问题讨论】:

  • 也许,只是也许,64 位编译器对DWORD(-1) 做了一些奇怪的事情——你用$FFFFFFFF 试过了吗?
  • 是相同的结果:误报。
  • 如果您附加二进制代码而不是 src,则更有用

标签: delphi winapi


【解决方案1】:

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

ATTACH_PARENT_PROCESS (DWORD)-1

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

这里您使用的是值ATTACH_PARENT_PROCESS

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

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

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

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

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

【讨论】:

  • 对不起,我的错。我的问题不清楚。您应该使用 GUI 程序。我已经更新了问题。
  • @JensBorrisholt 我已经更新了答案。我认为这就是正在发生的事情。
  • 好吧,简而言之:从调试器运行时,它在 64 位下无法工作
  • @JensBorrisholt 我想,虽然不清楚“工作”是什么意思——在 64 位调试中,总会有一个父控制台可供附加。如果您需要将此特定控制台与其他可能存在的父控制台区分开来,那么这当然是可能的。
猜你喜欢
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 2011-09-04
相关资源
最近更新 更多