【问题标题】:How to determine if I'm running as a console app? (Delphi on Win32)如何确定我是否作为控制台应用程序运行? (Win32 上的德尔福)
【发布时间】:2011-11-03 04:19:14
【问题描述】:

我有一个通用单元,它对 GExperts Debugger 和/或 OutputDebugString 进行一些日志记录。我将在控制台应用程序中使用它,所以我希望它能够通过writeln() 输出到标准输出。
主可执行文件已经有 {$APPTYPE CONSOLE} ,但我认为这对我没有帮助。日志记录例程将从几个地方调用:

  1. 主控制台应用程序,将链接到 BPL,
  2. 来自另一个“需要”第一个 bpl 的 BPL,并且.....
  3. 来自静态链接单元的 DLL。

BPL 和 DLL 将在 {$APPTYPE CONSOLE} 指令不可见的情况下构建,因此我不能使用 IFDEF 条件编译。 BPL 和 DLL 需要能够以任意一种方式运行,具体取决于主应用程序是常规的 winapp 还是控制台应用程序。

我想到的一个丑陋的解决方案是使用可执行文件的名称。例如:

if (UpperCase(ExtractFileName(ParamStr(0))) = 'MYCONSOLEAPP.EXE')  then ...

但我讨厌这样做,因为我可以拥有其他控制台应用程序...

我宁愿只拥有一个神奇的功能 AmIAConsoleApp : boolean; 有这样的吗? 我在这个项目上使用的是 Delphi2005。

更新:我发现我有点像 this question,但我想调查一下 Delphi 人员,看看是否有更好的方法。

【问题讨论】:

  • 有几个善意的、看起来很有帮助的答案建议使用 System.IsConsole。它们被海报删除了,但我觉得参与讨论很有价值。所以这就是它不起作用的原因:System.IsConsole 返回 true,根据文档,“{ True if compiled as console app }”。我没有编译为控制台应用程序(主应用程序是,但 DLL 不是)。所以我的结果好坏参半,具体取决于从哪里调用记录器。

标签: delphi console-application


【解决方案1】:

在创建实例时使用构造函数注入注入记录器。 Here's a simple example.

您提出的测试应用是否为控制台应用的解决方案仅适用于这两种情况。构造函数注入解决方案几乎不再是代码,并且可以在您需要输出的任何地方工作。

【讨论】:

  • 您的意思是类似于X := TY.Create(MyLogger) 的意思吗?然后控制台应用程序提供了一个使用 Writeln 的记录器,而 GUI 应用程序提供了另一个,甚至为零?一个好主意(尽管这个术语对我来说是新的)我在这种情况下使用过几次(例如需要 ICharProvider 的词法分析器/解析器:控制台测试应用程序提供了一个从一组字符串常量中获取字符的应用程序,而真正的应用程序提供了一个从 IDE 编辑器获取字符的应用程序)。
  • @Rudy,是的,我就是这个意思。
【解决方案2】:

致电GetStdHandle(Std_Output_Handle)。如果成功并返回零,则没有可写入的控制台。其他返回值表示控制台已附加到进程,因此您可以对其进行写入(尽管控制台可能不是在控制台程序中记录消息的最理想位置,因为它们会干扰正常输出)。像这样的:

function IAmAConsoleApp: Boolean;
var
  Stdout: THandle;
begin
  Stdout := GetStdHandle(Std_Output_Handle);
  Win32Check(Stdout <> Invalid_Handle_Value);
  Result := Stdout <> 0;
end;

【讨论】:

  • 此答案还涵盖了应用程序不是控制台类型但分配了一个的情况。所以我认为这是正确的答案,即使问题是错误的(最终目的是输出到控制台,而不是找出可执行文件是如何链接的)。
  • 酷 - 明天我会试一试。谢谢。
猜你喜欢
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多