Laden...

API: Dateiname von DateiHandle

Erstellt von Ayke vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.553 Views
Ayke Themenstarter:in
643 Beiträge seit 2006
vor 15 Jahren
API: Dateiname von DateiHandle

Hi,

ich suche einen Weg einen Dateinamen über ein FileHandle zu bekommen. Ist das überhaupt möglich ?

mfg

1.433 Beiträge seit 2006
vor 15 Jahren

Ich verstehe Deine Frage nicht ganz. Könntest Du diese ein bisschen genauer schildern?
Dateinamen herausfinden ist nicht schwert.

Dazu notwenidiger Namespace System.IO.
File Klasse

File Member

File Methoden

Grüsse
Daniel
Space Profile
Wer nicht fragt, der nicht gewinnt

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo schaedld,

Ich verstehe Deine Frage nicht ganz.

hm, die ist doch ziemlich eindeutig. Er hat einen Win32-FileHandle und will dazu den FileName wissen. Jetzt will er wissen, ob das geht und wenn ja mit welcher Funktion.

Hallo Ayke,

ich bin mir nicht sicher, ob das geht, denn es gibt ja auch FileHandle, die gar nicht mit einer Datei verbunden sind, z.B. stdout.

herbivore

1.433 Beiträge seit 2006
vor 15 Jahren

hm, die ist doch ziemlich eindeutig. Er hat einen Win32-FileHandle und will dazu den FileName wissen. Jetzt will er wissen, ob das geht und wenn ja mit welcher Funktion.

Grüsse
Daniel
Space Profile
Wer nicht fragt, der nicht gewinnt

3.511 Beiträge seit 2005
vor 15 Jahren

Ja, das geht.

Ist etwas kompliziert aber man steigt da recht fix durch.


public class NativeMethods
{
  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern bool GetFileSizeEx(SafeFileHandle hFile, out long lpFileSize);

  [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping", CharSet = CharSet.Unicode, SetLastError = true)]
  private static extern SafeFileHandle CreateFileMapping(SafeFileHandle hFile, uint lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);

  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern IntPtr MapViewOfFile(SafeFileHandle hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, IntPtr dwNumberOfBytesToMap);

  [DllImport("psapi.dll", SetLastError = true)]
  private static extern uint GetMappedFileName(IntPtr hProcess, IntPtr lpv, StringBuilder lpFilename, uint nSize);

  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

  private const uint PAGE_READONLY = 0x2;
  private const uint FILE_MAP_READ = 0x0004;
  private const int MAX_PATH = 260;

  public static string GetFileNameByHandle(SafeFileHandle hFile)
  {
    if (hFile.IsInvalid)
      throw new ArgumentException("Invalid handle: hFile");

    long lpFileSize;
    if (!GetFileSizeEx(hFile, out lpFileSize))
      Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

    if (lpFileSize == 0)
      throw new ArgumentException("Cannot map a file with a length of zero");

    using (SafeFileHandle hMappedFile = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, null))
    {
      if (hMappedFile.IsInvalid)
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

      IntPtr pMem = MapViewOfFile(hMappedFile, FILE_MAP_READ, 0, 0, IntPtr.Zero);

      if (pMem == IntPtr.Zero)
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

      StringBuilder lpFilename = new StringBuilder(MAX_PATH);

      if (GetMappedFileName(Process.GetCurrentProcess().Handle, pMem, lpFilename, MAX_PATH) == 0)
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

      if (!UnmapViewOfFile(pMem))
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

      return lpFilename.ToString();
    }
  }
}

Der Aufruf könnte dann so aussehen


using (FileStream fs = new FileStream("Foo.bar", FileMode.Open))
{
  Console.WriteLine(NativeFileMethods.GetFileNameByHandle("BlaDatei.bla"));
}

Das Ergebnis ist allerdings etwas gewöhnungsbedürftig und muss anschließend manuell nochmal durchgeparst werden. Wenn die Datei "Foo.bar" unter "C:\Temp" liegt, sieht das Ergebnis so aus


\Device\HarddiskDmVolumes\PhysicalDmVolumes\BlockVolume1\Temp\Foo.bar

Du musst also irgendwie schauen, das du den Partitionsnamen in den eigentlichen Laufwerksbuchstaben bekommst.

Achso, du musst natürlich über ein SafeFileHandle verfügen. Wenn du kein hast, kannst du einfach mit


SafeFileHandle sfh = new SafeFileHandle(IrgendEinIntPtr, false);

dir den SafeFileHandle holen.

Ach und noch was: Das ganze funktioniert IMHO nur, wenn der aktuelle Benutzer Administrationsrechte hat.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

Ayke Themenstarter:in
643 Beiträge seit 2006
vor 15 Jahren

Danke Khalid ! 🙂