从Windows NT设备路径转换为驱动器号路径

hjzp0vay  于 2023-04-07  发布在  Windows
关注(0)|答案(2)|浏览(485)

如何从设备路径中解析带有驱动器号的路径?
例如,转换

\Device\HarddiskVolume4\Windows\System32\RuntimeBroker.exe

进入

C:\Windows\System32\RuntimeBroker.exe

假设HarddiskVolume4Map到此计算机上的C:
我已经找到了this question,但我想在C#中使用它。

qco9c6ql

qco9c6ql1#

string devicePath = @"\Device\HarddiskVolume4\Windows\System32\RuntimeBroker.exe";
string driveLetterPath = DevicePathMapper.FromDevicePath(devicePath);

// driveLetterPath == C:\Windows\System32\RuntimeBroker.exe

因为我们想要一个带有驱动器号的路径,我们需要用正确的驱动器号替换\Device\HarddiskVolume4,例如C:。为此,使用QueryDosDevice并将dos设备Map到每个驱动器号。然后我们可以搜索和替换dos设备路径。
这是一个可能的实现。它使用内部扩展方法:

public static class DevicePathMapper {
    [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern uint QueryDosDevice([In] string lpDeviceName, [Out] StringBuilder lpTargetPath, [In] int ucchMax);

    public static string FromDevicePath(string devicePath) {
        var drive = Array.Find(DriveInfo.GetDrives(), d => devicePath.StartsWith(d.GetDevicePath(), StringComparison.InvariantCultureIgnoreCase));
        return drive != null ?
            devicePath.ReplaceFirst(drive.GetDevicePath(), drive.GetDriveLetter()) :
            null;
    }

    private static string GetDevicePath(this DriveInfo driveInfo) {
        var devicePathBuilder = new StringBuilder(128);
        return QueryDosDevice(driveInfo.GetDriveLetter(), devicePathBuilder, devicePathBuilder.Capacity + 1) != 0 ?
            devicePathBuilder.ToString() :
            null;
    }

    private static string GetDriveLetter(this DriveInfo driveInfo) {
        return driveInfo.Name.Substring(0, 2);
    }

    private static string ReplaceFirst(this string text, string search, string replace) {
        int pos = text.IndexOf(search);
        if (pos < 0) {
            return text;
        }
        return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
    }
}
mpbci0fu

mpbci0fu2#

替代实施方式:

public class PathConverter
{
    [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);

    public static string ConvertPath(string path)
    {
        DriveInfo[] drives = DriveInfo.GetDrives();
        StringBuilder sb = new(128);
        string search = "";
        int i = 0;

        for (; i < drives.Length; i++)
            if (path.StartsWith(search = QueryDosDevice(drives[i].Name[..2], sb.Clear(), sb.Capacity) != 0 ? sb.ToString() : ""))
                break;

        if (i == drives.Length)
            return path;
        else
            return path.Replace(search + "\\", drives[i].Name);
    }
}

相关问题