Как программно получить папку для загрузки Windows «% USERPROFILE% / Downloads»?

В .Net мы можем получить пути к «особым папкам», таким как «Документы / Рабочий стол» и т. Д. Сегодня я попытался найти способ получить путь к папке «Загрузки», но, похоже, он не настолько особенный.

Я знаю, что могу просто сделать 'C: \ Users \ Username \ Downloads', но это кажется уродливым решением. Итак, как я могу получить путь, используя .Net?

Ответы на вопрос(5)

это особенное, обнаружение имени этой папки не стало возможным до Vista. .NET по-прежнему необходимо поддерживать предыдущие операционные системы. Вы можете вызвать SHGetKnownFolderPath (), чтобы обойти это ограничение, например:

using System.Runtime.InteropServices;
...

public static string GetDownloadsPath() {
    if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
    IntPtr pathPtr = IntPtr.Zero;
    try {
        SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out pathPtr);
        return Marshal.PtrToStringUni(pathPtr);
    }
    finally {
        Marshal.FreeCoTaskMem(pathPtr);
    }
}

private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);
 Ray25 нояб. 2018 г., 18:54
Это единственный полностью правильный ответ здесь.
 Kiquenet14 мар. 2017 г., 14:43
Замечания: The user might have moved the folder to another location (which is quite easy in 8, 8.1 and 10)...
 Kiquenet14 мар. 2017 г., 12:30
Зачем использоватьSHGetKnownFolderPath и неEnvironment.SpecialFolder ?
 Hans Passant16 июн. 2013 г., 10:40
Вы, вероятно, можете выкопать его из реестра где-нибудь. Я не знаю где, я вышел на пенсию XP давным-давно. Regedit.exe полезно найти его обратно.
 Kiquenet14 мар. 2017 г., 14:57
С помощьюИмитатор с LOGON32_LOGON_INTERACTIVE не работаетEnvironment.GetFolderPath(Environment.SpecialFolder.Personal) ниSHGetKnownFolderPath ?
 Jenna Leaf26 окт. 2017 г., 21:23
Автор прав, решение "не красиво"! Почему он не улучшил это? Кроме того, вы никогда не должны искушать "path = Path.Combine (path," Downloads ")", потому что это просто предполагает, что загрузка клиентских окон - это [Downloads] - на самом деле это не так! Я переписал решение добавил новый ниже!
 Danny Beckett16 июн. 2013 г., 10:02
Есть ли способ заставить это работать на локализованной Windows, до Vista? То естьPath.Combine(path, "Downloads"); не будет работать, так как папка называетсяTéléchargementsнеDownloads.
Решение Вопроса

что он даст вам НЕПРАВИЛЬНЫЙ результат, если каталог загрузок по умолчанию был изменен на [Download1]! Правильный способ сделать это, охватывающий все возможности,

using System;
using System.Runtime.InteropServices;

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

    [Flags] public enum KnownFolderFlags : uint { SimpleIDList = 0x00000100
        , NotParentRelative = 0x00000200, DefaultPath = 0x00000400, Init = 0x00000800
        , NoAlias = 0x00001000, DontUnexpand = 0x00002000, DontVerify = 0x00004000
        , Create = 0x00008000,NoAppcontainerRedirection = 0x00010000, AliasOnly = 0x80000000
    }
    public static string GetPath(string RegStrName, KnownFolderFlags flags, bool defaultUser) {
        IntPtr outPath;
        int result = 
            SHGetKnownFolderPath (
                new Guid(RegStrName), (uint)flags, new IntPtr(defaultUser ? -1 : 0), out outPath
            );
        if (result >= 0)            {
            return Marshal.PtrToStringUni(outPath);
        } else {
            throw new ExternalException("Unable to retrieve the known folder path. It may not "
                + "be available on this system.", result);
        }
    }

}   

Чтобы проверить это, если вы специально хотите, чтобы ваш личный каталог загрузок, вы отметите по умолчанию false ->

using System.IO;
class Program    {
    [STAThread]
    static void Main(string[] args)        {
        string path2Downloads = string.Empty;
        path2Downloads = 
            cGetEnvVars_WinExp.GetPath("{374DE290-123F-4565-9164-39C4925E467B}", cGetEnvVars_WinExp.KnownFolderFlags.DontVerify, false);
        string[] files = { "" };
        if (Directory.Exists(path2Downloads)) {
            files = Directory.GetFiles(path2Downloads);
        }
    }//Main
}

Или только одна строка Environment.ExpandEnvironmentVariables () -> (самое простое решение).

using System.IO;
class Program    {
/* https://ss64.com/nt/syntax-variables.html */
    [STAThread]
    static void Main(string[] args)        {
        string path2Downloads = string.Empty;
        string[] files = { "" };
        path2Downloads = Environment.ExpandEnvironmentVariables(@"%USERPROFILE%\Downloads");
        if (Directory.Exists(path2Downloads)) {
            files = Directory.GetFiles(path2Downloads);
        }
    }//Main
}
 Dai18 мая 2018 г., 06:14
Ваш первый пример использованияSHGetKnownFolderPath будет утечка памяти. Документация дляSHGetKnownFolderPath говорит, что вызывающая сторона должна освободить значение `` ppszPath` с помощьюCoTaskMemFree. в то время как документация дляMarshal.PtrToStringUni говорит, что не освобождает строку, переданную ему.
 Ray25 нояб. 2018 г., 18:52
Почему вы используете жесткий код\Downloads опять в третьем примере кода? Это приводит к неверным примерам, как вы заявили ранее.
 BlackMarker13 авг. 2018 г., 15:45
Он пытается прочитать защищенную память и мгновенно переводит мое приложение в режим останова на сервере. Я отладил это, и это происходит наresult переменная вGetPath функционировать любое решение?

и он работает для .net 4.6 с Windows 7 и выше. Приведенный ниже код дает путь к папке профиля пользователя ->"C:\Users\<username>"

string userProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

Далее для доступа к папке загрузок просто объедините дополнительные строки пути, как показано ниже:

string DownloadsFolder = userProfileFolder + "\\Downloads\\";

Теперь конечный результат будет

"C:\Users\<username>\Downloads\"

Надеюсь, это сэкономит время для кого-то в будущем.

 Ray25 нояб. 2018 г., 18:52
Как указано в комментариях к другим ответам, делающим то же самое, это дает неправильные результаты, если папка была перемещена из папки профиля пользователя.

Dim Dd As String = Environment.GetFolderPath(Environment.SpecialFolder.Favorites)
Dim downloD As String = Dd.Replace("Favorites", "Downloads")
txt1.text = downLoD

это просто уловка, а не решение.

 Jenna Leaf26 окт. 2017 г., 20:50
Извините, я должен смеяться! Это милый трюк, но он все еще называется трюком (а не решением - он сломается на днях!): Замените «избранное» на «загрузки», ха-ха! Желаю, чтобы жизнь была такой легкой! (что если я поменяю место загрузки?)
 Gilad Green02 окт. 2016 г., 10:04
Публикация ответа на вопрос, опубликованный и отвеченный 6 лет назад. Пожалуйста, объясните, почему ваше решение лучше использовать, чем существующее.
 Kiquenet16 мар. 2017 г., 12:54
Не бог решение The user might have moved the folder to another location (which is quite easy in 8, 8.1 and 10). Получение всех «специальных папок» в .NET
 Kiquenet14 мар. 2017 г., 14:41
Пожалуйста, объясните, почему ваше решение лучше использовать, чем существующее? Лучше не использоватьSHGetKnownFolderPath ?

попробуйте ...

Dim strNewPath As String = IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) + "\Downloads\"
 Simon Mattes29 мар. 2016 г., 13:30
Не жесткие пути кода здесь. Пользователь мог переместить папку в другое место (что довольно легко в 8, 8.1 и 10) ...
 Ray11 июл. 2015 г., 14:59
Это неправильно, с. мои замечания здесь:codeproject.com/Articles/878605/...

Ваш ответ на вопрос