如何检测输出何时被重定向?

问题描述 投票:0回答:6

我有一个用 C 编写的 Win32 应用程序,可以将其控制台输出通过 printf() 重定向到日志文件。

如果我能有我的应用程序就好了。检测它是否是在有或没有重定向“>”的情况下启动的。

有什么想法吗?

winapi redirect console-application
6个回答
6
投票

汤姆,感谢您的意见。

我做了一些实验,发现这对我有用..

fpost_t pos ;

fgetpos (stdout, & pos) ;

当应用程序的输出重定向到文件时,

fgetpos()
pos
设置为零。这是有道理的,因为它是为你新打开的 stderr。
编辑:实际上,如果文本已重定向到日志/文件,则返回的值可能是正整数。所以在你的代码中你会有类似
if (pos >= 0) bfRedirected = TRUE;

的东西

当应用程序的输出没有被重定向时 - 它会转到控制台设备 - 而不是文件,因此

fgetpos()
会将
pos
设置为 -1。


2
投票

我认为管道本质上是盲目的,所以你没有内置的方法来判断你是否被重定向。此外,试图找出抽象层背后发生的事情是一个坏习惯。

如果您确实需要控制输出,请将日志文件名添加为命令行参数!

话虽如此,您可以进行一些聪明的猜测来找出答案:

  • 程序可以查询 shell 命令历史记录以找出最近执行的命令。
  • 如果您知道日志文件的路径,则可以扫描该目录并查看文件是否已创建或更改其大小。
  • 重定向和未重定向时的基准写入速度。仅当您的系统非常稳定并且环境条件不会改变时,这才有效。

1
投票

来自 Microsoft 的方法:WriteConsole 如果与重定向到文件的标准句柄一起使用,则会失败。如果应用程序处理可重定向的多语言输出,请判断输出句柄是否为控制台句柄(一种方法是调用 GetConsoleMode 函数并检查是否成功)。


1
投票

可靠的方法是使用

GetFinalPathNameByHandle
检查stdout文件句柄,如果没有重定向则会返回错误

TCHAR chPath[MAX_PATH];
if (GetFinalPathNameByHandle(GetStdHandle(STD_OUTPUT_HANDLE), chPath, MAX_PATH, 0))
    std::cout << "stdout redirected to " << chPath << '\n';
else
    std::cout << "stdout not redirected" << '\n';

该 API 从 Windows Vista 开始可用。在较旧的 Windows 上

GetMappedFileName
需要使用 像这样


0
投票

据我所知,答案是你不能。输出重定向的工作原理是简单地读取给定程序的输出流并将其重定向到另一个管道/流。文件/流的设计使得作者对读者一无所知,以至于您不应该知道您正在被阅读。

即使检测到有读卡器也是没有用的,因为正常情况下是有读卡器的。控制台正在读取程序的输出并将其显示在屏幕上。


0
投票

示例来自 https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/isatty?view=msvc-170

#include <stdio.h>
#include <io.h>

int main( void )
{
   if( _isatty( _fileno( stdout ) ) )
      printf( "stdout has not been redirected to a file\n" );
   else
      printf( "stdout has been redirected to a file\n");
}
© www.soinside.com 2019 - 2024. All rights reserved.