【问题标题】:How to open a file when file handle number is known?已知文件句柄号时如何打开文件?
【发布时间】:2011-04-03 12:20:24
【问题描述】:

我用 FileStream 在 C# 中打开一个文件,并通过这一行得到文件句柄号:

IntPtr file_handle = fs.SafeFileHandle.DangerousGetHandle();

现在我想将此句柄传递给 C++ 代码并使用此句柄值来访问文件。这可能吗?如何在 C++ 中仅使用文件句柄打开文件?

谢谢。

更新

我使用 C# P/Invoke 到 C++ Win32 DLL(不是 COM DLL)。我在 C# 中将文件作为 FileStream 打开,并将句柄传递给 C++。这是我在 C++ DLL 中的一些代码:

extern "C" __declspec(dllexport)void read_file(HANDLE file_handle)
{
    char buffer[64];
    ::printf("\nfile = %d\n",file_handle);

    if(::ReadFile(file_handle,buffer,32,NULL,NULL))
    {
        for(int i=0;i<32;i++)
            cout<<buffer[i]<<endl;
    }
    else
        cout<<"error"<<endl;
}

这是我的 C# 代码:

    [DllImport("...",EntryPoint = "read_file", CharSet = CharSet.Auto)]
    public static extern void read_file(IntPtr file_handle_arg);

但我收到此错误:

Unhandled Exception: System.AccessViolationException: Attempted to read or write
 protected memory. This is often an indication that other memory is corrupt.

谢谢。

【问题讨论】:

  • 您确定要这样做吗?即使可以做到,只是传递文件名可能会更简单......
  • 我的第一个问题是“为什么?”。这可能是可行的,但它会很丑陋。我宁愿退后一步,分析需要什么最终结果,看看是否有更清洁的方法。

标签: c# c++ interop


【解决方案1】:

您可以使用 win32 调用,就像文件流/文件构造函数一样(通过 p/invoke)。

.NET Reflector中破解打开,好像是在使用这个函数:

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern SafeFileHandle CreateFile(
  string lpFileName,
  int dwDesiredAccess,
  FileShare dwShareMode,
  SECURITY_ATTRIBUTES securityAttrs,
  FileMode dwCreationDisposition,
  int dwFlagsAndAttributes,
  IntPtr hTemplateFile);

这是官方参考:

http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

这只是为了打开文件,正如你所说的那样:

如何在 C++ 中仅使用文件句柄打开文件

如果你想读取一个已经打开的文件,你可能会遇到更多的麻烦。我不知道。您也许可以使用此功能:

[DllImport("kernel32.dll", SetLastError=true)]
internal static extern unsafe int ReadFile(
  SafeFileHandle handle,
  byte* bytes,
  int numBytesToRead,
  IntPtr numBytesRead_mustBeZero,
  NativeOverlapped* overlapped
);

http://msdn.microsoft.com/en-us/library/aa365467(v=VS.85).aspx

【讨论】:

  • 谢谢梅林,但是这个方法需要一个文件名,而我只有一个文件句柄。
  • @smwikipedia:你可能在我还在编辑我的帖子时写下了你的评论。查看第二个函数,ReadFile
【解决方案2】:

这完全取决于 - 但您不太可能做到这一点。我假设您的 C# 代码和 C++ 代码在不同的进程中运行——如果您在同一个进程中,您应该能够将 IntPtr 编组为 HANDLE

问题在于文件句柄是特定于进程的——您将无法在另一个进程中使用该句柄。

也就是说,你可能会更好:

  • 将文件名传递给 C++ 代码并在那里打开它
  • 将文件中实际包含的数据传递给 C++ 并在那里进行处理。

【讨论】:

  • 这可能比我的帖子更准确,因为文件句柄可能是特定于进程的。您可以尝试 ReadFile,如果这不起作用,您只需使用 C++ 函数打开文件,正如 Billy 所说的。
【解决方案3】:

如果 C++ 代码是 C++/CLI,那么根本不用处理句柄。只需将 FileStream 对象直接传递给您的 C++ 代码即可。

如果 C++ 是本机代码,那么您可以在通常对文件使用 Windows HANDLE 值的任何地方使用文件句柄,例如 ReadFileWriteFile。你不会使用句柄来打开一个文件,因为它已经打开了。如果您想要另一个句柄副本,或者如果您想将句柄提供给另一个进程,请使用DuplicateHandle。如果您需要使用类似 POSIX 的函数(如 _read_write)来获取值,则调用 _open_osfhandle 以获取文件描述符。您可以使用 _fdopen 将文件描述符包装到 C FILE* 流中。

【讨论】:

    【解决方案4】:

    原来标题并不是 OP 所追求的。

    但如果有人真的需要这样做(例如:重新打开具有不同权限的文件),您可能可以使用 GetFileInformationByHandle 的组合来获取文件 ID 和 OpenFileById

    FWIW。

    【讨论】:

      猜你喜欢
      • 2016-09-24
      • 1970-01-01
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多