检查程序是否将stderr重定向到stdout

时间:2016-07-09 18:36:55

标签: c++ winapi posix iostream

在C ++程序中,是否可以检查stderr是否重定向到stdout,反之亦然?基本上我想知道这两个文件描述符是否指向同一个地方。使用本机API的特定于平台的解决方案是可以的。

2 个答案:

答案 0 :(得分:2)

Linux,也可能是其他unix-like:fstat fds和比较dev:ino对。

答案 1 :(得分:1)

对于Windows 7及更高版本的控制台句柄 - 这是真正的文件句柄(在XP上这不是真的,关于vista - 不记得了)。我们可以通过使用STD_OUTPUT_HANDLE和STD_ERROR_HANDLE调用GetStdHandle获得这2个句柄。但后来需要以某种方式通过句柄比较文件。这不等于直接比较处理值 - 因为2个不同的句柄可以指向同一个文件。即使我们从句柄获得指向FILE_OBJECT的指针(这可能来自用户模式) - 两个不同的FILE_OBJECT可以指向同一个文件(如果我们谈论文件系统文件)。所以我认为最好的方式 - 得到两个文件的名称 - 并进行比较 - 它们是否相等。这可以通过ZwQueryObject来完成。代码可以像这样

NTSTATUS QueryName(HANDLE hFile, PUNICODE_STRING Name)
{
    union {
        PVOID buf;
        POBJECT_NAME_INFORMATION poni;
    };

    static volatile UCHAR guz;
    PVOID stack = alloca(guz);

    ULONG cb = 0, rcb = 512;
    NTSTATUS status;

    do 
    {
        if (cb < rcb)
        {
            cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
        }

        if (0 <= (status = ZwQueryObject(hFile, ObjectNameInformation, buf, cb, &rcb)))
        {
            return RtlDuplicateUnicodeString(0, &poni->Name, Name);
        }

    } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW);

    return status;
}

NTSTATUS AreFilesTheSame(HANDLE h1, HANDLE h2, PBOOL pb)
{
    if (h1 == h2)
    {
        *pb = TRUE;
        return STATUS_SUCCESS;
    }

    if (!h1 || !h2)
    {
        *pb = FALSE;
        return STATUS_SUCCESS;
    }

    UNICODE_STRING name1, name2;
    NTSTATUS status;

    if (0 <= (status = QueryName(h1, &name1)))
    {
        if (0 <= (status = QueryName(h2, &name2)))
        {
            *pb = RtlEqualUnicodeString(&name1, &name2, TRUE);
            RtlFreeUnicodeString(&name2);
        }
        RtlFreeUnicodeString(&name1);
    }

    return status;
}

BOOL b;
AreFilesTheSame(GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE), &b);

但对于xp,这将不起作用