在C#中打开管道连接到文件描述符

5

我有一个旧的应用程序,它从文件描述符3中读取客户端程序的消息。这是一个外部应用程序,所以我无法更改它。客户端是用C#编写的。如何在C#中打开到特定文件描述符的连接?我们可以使用类似AnonymousPipeClientStream()的东西吗?但是我们如何指定要连接的文件描述符?

2个回答

5

很遗憾,如果没有先使用本地Windows API的P/Invoke,您将无法完成此操作。

首先,您需要通过本机P/Invoke调用来打开文件描述符。这可以通过OpenFileById WINAPI函数完成。在MSDN上这里有如何使用它的说明,在MSDN论坛上这里有详细解释,并且在pinvoke.net这里提供了一些帮助,教您如何构建P/Invoke调用。

一旦您获得了文件句柄,就需要在安全的、托管的C#中将其包装在SafeFileHandle中:

// nativeHandle is the WINAPI handle you have acquired with the P/Invoke call
SafeFileHandle safeHandle = new SafeFileHandle(nativeHandle, true);

现在您可以直接打开文件流:
Stream stream = new FileStream(safeHandle, FileAccess.ReadWrite);

从这个点开始,你可以像在C#中使用任何其他文件或流一样使用它。完成后不要忘记处理你的对象。


这些文件 ID 是否与 C 运行时文件描述符相同?另外,OpenByFileId 仅在 Vista 或更高版本上受支持。 - John Saunders

2

我能够通过使用_get_osfhandle解决同样的问题。示例:

using System;
using System.IO;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;

class Comm : IDisposable
{
    [DllImport("MSVCRT.DLL", CallingConvention = CallingConvention.Cdecl)]
    extern static IntPtr _get_osfhandle(int fd);

    public readonly Stream Stream;

    public Comm(int fd)
    {
        var handle = _get_osfhandle(fd);
        if (handle == IntPtr.Zero || handle == (IntPtr)(-1) || handle == (IntPtr)(-2))
        {
            throw new ApplicationException("invalid handle");
        }

        var fileHandle = new SafeFileHandle(handle, true);
        Stream = new FileStream(fileHandle, FileAccess.ReadWrite);
    }

    public void Dispose()
    {
        Stream.Dispose();
    }       
}

嗨,Tim,我正在尝试使用你的代码来为FD3生成一个句柄,但是_get_osfhandle返回-1,这让你想起了什么吗? - hardkoded
1
@hardkoded:不会的。我建议在DllImport上使用SetLastError = True,以查看底层错误是什么。 - user142162
_get_osfhandle 是通用 CRT 的一部分,而不是 Windows API。它不会设置调用线程的最后一个错误代码。要求 CLR 为您保留它将会保留一个无意义的值。 - IInspectable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接