Потратив некоторое время на изучение классов и методов Windows.Storage, я был немного шокирован, обнаружив, что нет простого способа получить список внутренних дисков на машине с помощью UWP. Я нашел такие примеры: Как получить логические диски имена в Windows 10?, но это касается только съемных дисков (флэш-накопители, DVD-привод и т. д.).

Я знаю, что могу позволить пользователю выбрать папку, и это предоставит мне дескриптор выбранного диска, но это кажется неуклюжим, поскольку я хочу, чтобы пользователь мог запускать мое программное обеспечение и сканировать внутренние диски на ПК без приходиться каждый раз заново выбирать диски.

Я добавил атрибут broadFileSystemAccess в манифест, чтобы иметь доступ к дискам, я просто не могу вызвать метод для получения внутренних дисков. В качестве обходного пути я написал следующий метод.

public List<StorageFolder> GetInternalDrives()
{
    string driveLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int driveLettersLen = driveLetters.Length;
    string removableDriveLetters = "";
    string driveLetter;

    List<StorageFolder> drives = new List<StorageFolder>();
    StorageFolder removableDevices = KnownFolders.RemovableDevices;
    IReadOnlyList<StorageFolder> folders = Task.Run<IReadOnlyList<StorageFolder>>(async () => await removableDevices.GetFoldersAsync()).Result;

    foreach (StorageFolder removableDevice in folders)
    {
        if (string.IsNullOrEmpty(removableDevice.Path)) continue;
        driveLetter = removableDevice.Path.Substring(0, 1).ToUpper();
        if (driveLetters.IndexOf(driveLetter) > -1) removableDriveLetters += driveLetter;
    }

    for (int curDrive = 0; curDrive < driveLettersLen; curDrive++)
    {
        driveLetter = driveLetters.Substring(curDrive, 1);
        if (removableDriveLetters.IndexOf(driveLetter) > -1) continue;

        try
        {
            StorageFolder drive = Task.Run<StorageFolder>(async () => await StorageFolder.GetFolderFromPathAsync(driveLetter + ":")).Result;
            drives.Add(drive);
        }
        catch (System.AggregateException) { }

    }

    return drives;
}

А вот пример вызова GetInternalDrives:

List<StorageFolder> drives = GetInternalDrives();
panScanParams.Children.Clear();
foreach (StorageFolder drive in drives)
{
    CheckBox cb = new CheckBox();
    cb.Content = drive.DisplayName;
    cb.IsChecked = true;
    panScanParams.Children.Add(cb);
}

Хотя код вызывается только один раз для экземпляра приложения, я совершенно не доволен кодом. Поскольку он вызывает StorageFolder.GetFolderFromPathAsync для каждой буквы алфавита, на моей машине происходит сбой более 20 раз. Написание кода, который, как вы ожидаете, потерпит неудачу, и обработка исключения кажется плохой практикой. Но из-за отсутствия подходящей альтернативы я не знаю, какие еще у меня есть варианты.

Кто-нибудь занимался той же проблемой, и если да, то что вы сделали для ее решения?

0
Mathew Rimmington 21 Окт 2019 в 23:50

1 ответ

Лучший ответ

Или вы можете попробовать этот код var driveLetters = DriveInfo.GetDrives().Select(x => x.RootDirectory.Root).ToList().OrderBy(x => x.Root.FullName).ToList(); для получения дисков вместо использования метода StorageFolder для исключения одного за другим. После этого просматриваем полученный список и конвертируем в StorageFolder. Ниже кода я не удалял съемные диски.

var driveLetters = DriveInfo.GetDrives().Select(x => x.RootDirectory.Root).ToList().OrderBy(x => x.Root.FullName).ToList();
List<StorageFolder> drives = new List<StorageFolder>();
foreach (var driveInfo in driveLetters)
{
    String a = driveInfo.ToString();
    StorageFolder drive = Task.Run<StorageFolder>(async () => await StorageFolder.GetFolderFromPathAsync(a)).Result;
    drives.Add(drive);
}
2
Faywang - MSFT 24 Окт 2019 в 09:54