Вопрос по c# – Получение папки с загрузками в C #? [Дубликат]

28

This question already has an answer here:

How to programmatically derive windows downloads folder “%USERPROFILE%/Downloads”? 5 answers

Я сделал некоторый код, который будет искать каталоги и отображать файлы в списке.

DirectoryInfo dinfo2 = new DirectoryInfo(@"C:\Users\Hunter\Downloads");
FileInfo[] Files2 = dinfo2.GetFiles("*.sto");
foreach (FileInfo file2 in Files2)
{
     listBox1.Items.Add(file2.Name);
}

Я даже попробовал это:

string path = Environment.SpecialFolder.UserProfile + @"\Downloads";
DirectoryInfo dinfo2 = new DirectoryInfo(Environment.SpecialFolder.UserProfile + path);
FileInfo[] Files2 = dinfo2.GetFiles("*.sto");
foreach (FileInfo file2 in Files2)
{
     listBox1.Items.Add(file2.Name);
}

Я получаю ошибку, хотя ...

Хорошо, где это говоритUsers\Hunter Ну, когда люди получают мое программное обеспечение, его имя не охотник ... так как мне сделать, чтобы оно попало туда, где оно находится в любой папке загрузок пользователя?

Может быть, используяEnvironment.SpecialFolder enum ? ты пробовалpath = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Personal)); path = Path.Combine(path, "Downloads"); ? Kiquenet

Ваш Ответ

6   ответов
0

public static string getHomePath()
{
    // Not in .NET 2.0
    // System.Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
    if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
        return System.Environment.GetEnvironmentVariable("HOME");

    return System.Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%");
}


public static string getDownloadFolderPath()
{
    if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
    {
        string pathDownload = System.IO.Path.Combine(getHomePath(), "Downloads");
        return pathDownload;
    }

    return System.Convert.ToString(
        Microsoft.Win32.Registry.GetValue(
             @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
            ,"{374DE290-123F-4565-9164-39C4925E467B}"
            ,String.Empty
        )
    );
}
В Unix, где нет эквивалента пользовательской Windows «Загрузки», определенной пользователем. папка, вы жестко закодировали имя папки. В Windows вместо вызоваSHGetKnownFolderPath() Если вы работаете так, как вы предполагаете, вы пытаетесь получить папку прямо из реестра. В любом случае, этот ответ бесполезен и потенциально вреден для тех, кто его использует.
@Peter Duniho: На самом деле, я изменил цель для "Загрузок", поэтому я написал код в первую очередь. Это единственное, что работало в .NET 2.0. Остальные не дали или дали неверные результаты.
Этот ключ содержит зловещий ключ с именем"!Do not use this registry key" и значение"Use the SHGetFolderPath or SHGetKnownFolderPath function instead"  ключ был поставлен разработчиком Microsoft Раймондом Ченом, Microsoft Chuck Norris.Why is there the message ‘!Do not use this registry key’ in the registry? The long and sad story of the Shell Folders key
@Peter Duniho: В Ubuntu Linux (System.PlatformID.Unix - поскольку у не-ядра .NET нет отдельного идентификатора платформы для Linux), каталог загрузки называется & quot; Загрузки & quot; и находится в домашнем каталоге пользователя (по умолчанию). MacOS, к сожалению, проваливается, так как PlatformID.Unix также возвращает true в MacOS, а platformID MacOSX также возвращает true в Linux. Не уверен, что кто-то серьезно использует Unix. Но, если хотите, вы всегда можете вызвать собственные вызовы как в Unix / Linux, так и в Windows, что потребует добавления зависимости от Mono.Unix, если вы сделаете это правильно. Я предпочитаю не добавлять такие зависимости
Этот ответ просто неправильный. В то время какdefault значение для специальной папки & quot; Загрузки & quot; папка с именем & quot; Загрузки & quot; В домашнем каталоге профиля пользователя пользователь может легко изменить & quot; Загрузки & quot; специальная папка для любого другого места, к которому они имеют доступ. Вышеwill not work для любого пользователя, который изменил цель & quot; Загрузки & quot; специальная папка.
5

Самый простой способ это:

Process.Start("shell:Downloads");

Если вам нужно только получить путь к папке загрузки текущего пользователя, вы можете использовать это:

Я извлек его из кода @PacMani.

 // using Microsoft.Win32;
string GetDownloadFolderPath() 
{
    return Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "{374DE290-123F-4565-9164-39C4925E467B}", String.Empty).ToString();
}
Этот ключ содержит зловещий ключ с именем"!Do not use this registry key" и значение"Use the SHGetFolderPath or SHGetKnownFolderPath function instead"  ключ был поставлен разработчиком Microsoft Раймондом Ченом, Microsoft Chuck Norris.Why is there the message ‘!Do not use this registry key’ in the registry? The long and sad story of the Shell Folders key
"!Do not use this registry key" Getting All "Special Folders" in .NET
79

SHGetKnownFolderPath является единственным правильным способом получения путей к специальным папкам, включая личные и папку «Загрузки».

Существуют и другие способы получения аналогичных результатов, которые выглядят многообещающими, но в итоге приводят к совершенно неправильным путям в конкретных системах (например, объединение или жесткое кодирование частей пути или злоупотребление старым ключом реестра). Причина этого указана вмоя статья CodeProject, который также перечисляет полное решение. Он предоставляет класс обёртывания с поддержкой извлечения всех известных 94 специальных папок и ещё нескольких вкусностей.

Для быстрого примера здесь я просто вставил сокращенную версию решения, имея возможность извлекать только личные специальные папки, такие как «Загрузки»:

using System;
using System.Runtime.InteropServices;

/// <summary>
/// Class containing methods to retrieve specific file system paths.
/// </summary>
public static class KnownFolders
{
    private static string[] _knownFolderGuids = new string[]
    {
        "{56784854-C6CB-462B-8169-88E350ACB882}", // Contacts
        "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}", // Desktop
        "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}", // Documents
        "{374DE290-123F-4565-9164-39C4925E467B}", // Downloads
        "{1777F761-68AD-4D8A-87BD-30B759FA33DD}", // Favorites
        "{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}", // Links
        "{4BD8D571-6D19-48D3-BE97-422220080E43}", // Music
        "{33E28130-4E1E-4676-835A-98395C3BC3BB}", // Pictures
        "{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}", // SavedGames
        "{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}", // SavedSearches
        "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}", // Videos
    };

    /// <summary>
    /// Gets the current path to the specified known folder as currently configured. This does
    /// not require the folder to be existent.
    /// </summary>
    /// <param name="knownFolder">The known folder which current path will be returned.</param>
    /// <returns>The default path of the known folder.</returns>
    /// <exception cref="System.Runtime.InteropServices.ExternalException">Thrown if the path
    ///     could not be retrieved.</exception>
    public static string GetPath(KnownFolder knownFolder)
    {
        return GetPath(knownFolder, false);
    }

    /// <summary>
    /// Gets the current path to the specified known folder as currently configured. This does
    /// not require the folder to be existent.
    /// </summary>
    /// <param name="knownFolder">The known folder which current path will be returned.</param>
    /// <param name="defaultUser">Specifies if the paths of the default user (user profile
    ///     template) will be used. This requires administrative rights.</param>
    /// <returns>The default path of the known folder.</returns>
    /// <exception cref="System.Runtime.InteropServices.ExternalException">Thrown if the path
    ///     could not be retrieved.</exception>
    public static string GetPath(KnownFolder knownFolder, bool defaultUser)
    {
        return GetPath(knownFolder, KnownFolderFlags.DontVerify, defaultUser);
    }

    private static string GetPath(KnownFolder knownFolder, KnownFolderFlags flags,
        bool defaultUser)
    {
        int result = SHGetKnownFolderPath(new Guid(_knownFolderGuids[(int)knownFolder]),
            (uint)flags, new IntPtr(defaultUser ? -1 : 0), out IntPtr outPath);
        if (result >= 0)
        {
            string path = Marshal.PtrToStringUni(outPath);
            Marshal.FreeCoTaskMem(outPath);
            return path;
        }
        else
        {
            throw new ExternalException("Unable to retrieve the known folder path. It may not "
                + "be available on this system.", result);
        }
    }

    [DllImport("Shell32.dll")]
    private static extern int SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken,
        out IntPtr ppszPath);

    [Flags]
    private enum KnownFolderFlags : uint
    {
        SimpleIDList              = 0x00000100,
        NotParentRelative         = 0x00000200,
        DefaultPath               = 0x00000400,
        Init                      = 0x00000800,
        NoAlias                   = 0x00001000,
        DontUnexpand              = 0x00002000,
        DontVerify                = 0x00004000,
        Create                    = 0x00008000,
        NoAppcontainerRedirection = 0x00010000,
        AliasOnly                 = 0x80000000
    }
}

/// <summary>
/// Standard folders registered with the system. These folders are installed with Windows Vista
/// and later operating systems, and a computer will have only folders appropriate to it
/// installed.
/// </summary>
public enum KnownFolder
{
    Contacts,
    Desktop,
    Documents,
    Downloads,
    Favorites,
    Links,
    Music,
    Pictures,
    SavedGames,
    SavedSearches,
    Videos
}

(Полностью прокомментированная версия находится в статье CodeProject, ссылки на которую приведены выше.)

Хотя это была просто неприятная стена кода, поверхность, с которой вам приходится иметь дело, довольно проста. Вот пример консольной программы, выводящей путь к папке «Загрузки».

private static void Main()
{
    string downloadsPath = KnownFolders.GetPath(KnownFolder.Downloads);
    Console.WriteLine("Downloads folder path: " + downloadsPath);
    Console.ReadLine();
}

Например, просто позвонитеKnownFolders.GetPath() сKnownFolder enum значение папки, путь к которой вы хотите запросить.

NuGet Package

Если вы не хотите проходить через все это, просто установите мой недавно созданный пакет NuGet. ЗдесьСайт проектаи здесьссылка на галерею (обратите внимание, что использование отличается и полируется, пожалуйста, обратитесь к разделу Использование на сайте проекта для получения дополнительной информации).

PM> Install-Package Syroot.Windows.IO.KnownFolders

Использование:

using System;
using Syroot.Windows.IO;

class Program
{
    static void Main(string[] args)
    {
        string downloadsPath = new KnownFolder(KnownFolderType.Downloads).Path;
        Console.WriteLine("Downloads folder path: " + downloadsPath);
        Console.ReadLine();
    }
}
Я только что попробовал ваше (полное) решение с сайта codeproject, и оно отлично работает - спасибо. Рассматривали ли вы обернуть это в пакет Nuget?
Я еще не написал пакет NuGet, сам использую их редко, но, вероятно, это будет интересный урок, чтобы научиться создавать эти пакеты. Я просто не знаю, когда доберусь до него сейчас.
Хорошо, это совершенно нормально. Я использую их все время - это отличный способ управлять зависимостями от других частей кода (установка, управление версиями и т. Д.). Если вы примете вызов и создадите пакет nuget за один день, не могли бы вы обновить этот ответ и свой сайт codeproject со ссылкой на пакет? - тогда мы, надеюсь, сможем его найти;)
Этот класс, по-видимому, не работает в vs2015 - он жалуется, что GetPath не имеет 3 параметров - что верно, в коде нет упоминаний об этом.
@BugFinder: Да, скопируйте класс из связанной статьи CodeProject, так как это всего лишь отрывок.
0

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

Затем в своем коде считайте значение, из которого оно хранится.

ИМХО, лучше удалите ответ, потому что не полезно. Не очень хороший ответ, потому чтоreinvent the wheel. App.config не требуется, толькоWinAPI Getting All "Special Folders" in .NET
0

http://msdn.microsoft.com/en-us//library/system.environment.specialfolder.aspx

Есть переменные с путем к некоторым специальным папкам.

более новые папки, существующие после Windows Vista, не перечислены в перечислении SpecialFolder.The list of special folders published in MSDN
Environment.GetFolderPath (Environment.SpecialFolder.UserProfile)) + & quot; \ Downloads & quot ;; // моя вина, извините
подождите, когда я добавлю это в свой код, я получаю сообщение об ошибке:Could not find a part of the path 'C:\Users\Hunter\Documents\Visual Studio 2010\Projects\Setup Mover2\Setup Mover2\bin\Debug\UserProfile\Downloads\'. Hunter Mitchell
ИМХО, лучше удалите ответ, потому что не полезно. Не очень хороший ответ, потому чтоDownloads являетсяNOT value Specialfolder enum и используйте & quot; \ Downloads & quot; работает только в системах EN- *. А такжеuser can change location, Полное объяснениеGetting All "Special Folders" in .NET
@Marduk Пожалуйста, удалите свои комментарии, поскольку они предоставляют решение, которое работает только на английских системах, и даже только некоторые из них.
0

string download = Environment.GetEnvironmentVariable("USERPROFILE")[email protected]"\"+"Downloads";

Этот ответ просто неправильный. В то время какdefault значение для специальной папки & quot; Загрузки & quot; папка с именем & quot; Загрузки & quot; В домашнем каталоге профиля пользователя пользователь может легко изменить & quot; Загрузки & quot; специальная папка для любого другого места, к которому они имеют доступ. Вышеwill not work для любого пользователя, который изменил цель & quot; Загрузки & quot; специальная папка.
ИМХО, лучше удалите ответ, потому что не полезно. Не очень хороший ответ, потому чтоDownloads являетсяNOT value Specialfolder enum и используйте & quot; \ Downloads & quot; работает только в системах EN- *. А такжеuser can change location, Полное объяснениеGetting All "Special Folders" in .NET
У меня есть машина с Windows 10 на испанском языке. Работает нормально, никаких конфликтов.
Это всего лишь кодовый ответ, мы ожидаем немного больше хороших ответов. Техническое примечание: это сломается на международной версии окон. Принятый ответ на вопрос - правильный способ сделать это, который будет работать на всех версиях Windows.

Похожие вопросы