【问题标题】:Getting Downloads Folder in C#? [duplicate]在 C# 中获取下载文件夹? [复制]
【发布时间】:2012-05-26 21:02:49
【问题描述】:

我编写了一些代码来搜索目录并在列表框中显示文件。

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 不要那样做,看我的回答。

标签: c# directory visual-c#-express-2010


【解决方案1】:

【讨论】:

  • 等等,当我把它放在我的代码中时,我得到一个错误:找不到路径的一部分'C:\Users\Hunter\Documents\Visual Studio 2010\Projects\安装 Mover2\Setup Mover2\bin\Debug\UserProfile\Downloads\'。
  • Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)) + "\Downloads"; // 我的错,对不起
  • @Marduk 请删除您的 cmets,因为它们提供的解决方案仅适用于英语系统,甚至仅适用于其中一些系统。
  • 恕我直言,更好,删除答案,因为没有用。不好的答案,因为 DownloadsNOT value Specialfolder enum 并且使用“\Downloads”仅适用于 EN-* 系统。 用户可以更改位置。完整解释Getting All "Special Folders" in .NET
  • 自 Windows Vista 以来存在的较新文件夹未列在 SpecialFolder 枚举中。 The list of special folders published in MSDN
【解决方案2】:

通常,您的软件应具有一个可配置的变量,该变量存储用户的下载文件夹,可由用户分配,并在未设置时提供默认值。您可以将值存储在应用配置文件或注册表中。

然后在您的代码中读取存储位置的值。

【讨论】:

【解决方案3】:

WinAPI 方法SHGetKnownFolderPath 是检索特殊文件夹(包括个人文件夹和下载文件夹)路径的唯一正确方法。

还有其他方法可以获得类似的结果,看起来很有希望,但最终在特定系统上会出现完全错误的路径(例如,组合或硬编码路径的部分或滥用旧的注册表项)。其背后的原因在my CodeProject article 中说明,其中还列出了完整的解决方案。它提供了一个包装类,支持检索所有已知的 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 枚举值。

NuGet 包

如果您不想经历所有这些麻烦,只需安装我最近创建的 NuGet 包。这里是project site,这里是gallery link(注意用法不同,经过打磨,更多信息请查阅项目网站的Usage部分)。

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 文章中复制类,因为这只是摘录。
【解决方案4】:

最简单的方法是:

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();
}

【讨论】:

【解决方案5】:

string download = Environment.GetEnvironmentVariable("USERPROFILE")+@"\"+"Downloads";

【讨论】:

  • 这只是一个代码答案,我们期待更多的好答案。技术说明:这将在国际版 Windows 上中断。该问题的公认答案是正确的方法,适用于所有版本的 Windows。
  • 恕我直言,更好,删除答案,因为没有用。不好的答案,因为 DownloadsNOT value Specialfolder enum 并且使用“\Downloads”仅适用于 EN-* 系统。 用户可以更改位置。完整解释Getting All "Special Folders" in .NET
  • 这个答案是完全错误的。虽然特殊文件夹“Downloads”的 default 值是用户配置文件主目录下名为“Downloads”的文件夹,但用户可以将“Downloads”特殊文件夹更改为任何其他位置他们可以访问。上述对修改了“Downloads”特殊文件夹的目标的任何用户都不起作用
  • 我有一台装有西班牙语 Windows 10 的机器。炒锅很好,没有冲突。
  • 这会在我的机器上中断。我的机器有一个 SSD 和机械硬盘。因此,虽然用户配置文件位于 C: - 桌面、下载、文档、图片、音乐、视频文件夹都在 D: 驱动器上,纯粹是为了存储空间。个人觉得不好回答。
【解决方案6】:

跨平台版本:

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
        )
    );
}

【讨论】:

  • 该键包含一个名为 "的不祥键!请勿使用此注册表键" 和值 "改用 SHGetFolderPath 或 SHGetKnownFolderPath 函数” 密钥是由 Microsoft 开发人员 Raymond Chen,“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
  • "!请勿使用此注册表项" Getting All "Special Folders" in .NET
  • 这个答案是完全错误的。虽然特殊文件夹“Downloads”的 default 值是用户配置文件主目录下名为“Downloads”的文件夹,但用户可以将“Downloads”特殊文件夹更改为任何其他位置他们可以访问。上述对修改了“Downloads”特殊文件夹的目标的任何用户都不起作用
  • @Peter Duniho:实际上,我已经修改了“下载”的目标,这就是我首先编写代码的原因。这是 .NET 2.0 中唯一有效的方法。其余的没有,或者给出了错误的结果。
  • 在 Unix 上,没有与 Windows 用户定义的“下载”文件夹等效的文件夹,您可以硬编码文件夹名称。在 Windows 上,您尝试直接从注册表中获取文件夹,而不是像您应该调用的那样调用 SHGetKnownFolderPath() 函数。无论哪种方式,这个答案对使用它的人都没有用并且可能有害。
猜你喜欢
  • 2012-07-09
  • 1970-01-01
  • 2012-08-23
  • 2020-08-18
  • 2016-11-07
  • 2011-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多