2008-10-29 7 views
2

У меня есть устаревшее приложение, где оно читает сообщение из клиентской программы из дескриптора файла 3. Это внешнее приложение, поэтому я не могу его изменить. Клиент написан на C#. Как мы можем открыть соединение с конкретным дескриптором файла в C#? Можем ли мы использовать что-то вроде AnonymousPipeClientStream()? Но как мы указываем файловый дескриптор для подключения?Открытие соединения с файловым дескриптором в C#

ответ

2

К сожалению, вы не сможете этого сделать, не используя P/Invoking для родного Windows API.

Во-первых, вам нужно будет открыть дескриптор файла с помощью собственного вызова P/Invoke. Это выполняется функцией OpenFileById WINAPI. Here's how to use it на MSDN, here's an other link, подробно объясняя это на форумах MSDN и here's some help (pinvoke.net) о том, как создать свой вызов P/Invoke.

После того, как вы получили дескриптор файла, вам нужно обернуть его в SafeFileHandle, на этот раз в сейф, управляемый C#:

// 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#. Не забудьте убрать свои объекты, как только закончите.

+0

Являются ли эти идентификаторы файлов такими же, как дескрипторы файла времени выполнения C? Кроме того, OpenByFileId поддерживается только в Vista или более поздней версии. – 2011-01-07 15:50:51

0

Я смог решить ту же проблему, используя _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(); 
    }  
}