我有一个旧的应用程序,它从文件描述符3中读取客户端程序的消息。这是一个外部应用程序,所以我无法更改它。客户端是用C#编写的。如何在C#中打开到特定文件描述符的连接?我们可以使用类似AnonymousPipeClientStream()的东西吗?但是我们如何指定要连接的文件描述符?
我有一个旧的应用程序,它从文件描述符3中读取客户端程序的消息。这是一个外部应用程序,所以我无法更改它。客户端是用C#编写的。如何在C#中打开到特定文件描述符的连接?我们可以使用类似AnonymousPipeClientStream()的东西吗?但是我们如何指定要连接的文件描述符?
很遗憾,如果没有先使用本地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#中使用任何其他文件或流一样使用它。完成后不要忘记处理你的对象。
我能够通过使用_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();
}
}
DllImport
上使用SetLastError = True
,以查看底层错误是什么。 - user142162_get_osfhandle
是通用 CRT 的一部分,而不是 Windows API。它不会设置调用线程的最后一个错误代码。要求 CLR 为您保留它将会保留一个无意义的值。 - IInspectable