在C#中获取下载文件夹?

Hun*_*ell 36 c# directory visual-c#-express-2010

我已经制作了一些代码来搜索目录并在列表框中显示文件.

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

我甚至试过这个:

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);
}
Run Code Online (Sandbox Code Playgroud)

我收到了一个错误...

好吧,它说的Users\Hunter好吧,当人们拿到我的软件时,这个名字并不是猎人......所以我怎么把它带到任何用户下载文件夹的位置?

Ray*_*Ray 97

WinAPI方法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
}
Run Code Online (Sandbox Code Playgroud)

(在上面链接的CodeProject文章中可以找到完全注释的版本.)

虽然这只是一个令人讨厌的代码墙,但您必须处理的表面非常简单.以下是输出Downloads文件夹路径的控制台程序示例.

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

例如,只需KnownFolders.GetPath()使用KnownFolder文件夹的枚举值调用您要查询的路径.

NuGet包

如果您不想通过所有这些hazzle,只需安装我最近创建的NuGet包.这是项目网站,这里是图库链接(请注意,使用情况不同并且已经完善,请参阅项目网站上的"使用"部分以获取更多信息).

PM> Install-Package Syroot.Windows.IO.KnownFolders
Run Code Online (Sandbox Code Playgroud)

用法:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我刚刚在codeproject网站上尝试了您的(完整)解决方案,并且效果很好-谢谢。您是否考虑过将其包装在nuget包中? (3认同)
  • 我还没有编写NuGet程序包,我自己很少使用它们,但是教自己创建这些程序包可能是一个有趣的课程。我只是不知道什么时候到现在。 (2认同)
  • 这个类在 vs2015 中似乎不起作用 - 它抱怨 GetPath 没有 3 个参数 - 这是正确的,代码中没有提到这一点。 (2认同)

Gur*_*ile 7

最简单的方法是:

Process.Start("shell:Downloads");
Run Code Online (Sandbox Code Playgroud)

如果您只需要获取当前用户的下载文件夹路径,则可以使用以下命令:

我从@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();
}
Run Code Online (Sandbox Code Playgroud)

  • 该密钥包含一个名为***的不祥密钥"!不要使用此注册表项"***和值***"使用SHGetFolderPath或SHGetKnownFolderPath函数代替"***密钥由Microsoft开发人员放在那里Raymond Chen,"微软的查克诺里斯".[为什么在注册表中有'!不要使用此注册表项'的消息?](https://blogs.msdn.microsoft.com/oldnewthing/20110322-00/?p=11163)[漫长而悲伤的故事] Shell文件夹密钥](https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=41973/) (8认同)
  • ***“!不要使用此注册表项”*** [获取.NET中的所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-folders-in -网) (2认同)

小智 6

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

  • 这只是一个代码答案,我们期待更多好的答案。技术说明:这将在国际版 Windows 上崩溃。该问题的公认答案是正确的方法,适用于所有版本的 Windows。 (4认同)
  • 恕我直言,更好,删除答案,因为没有用。不是很好的答案,因为 *Downloads* 不是值 Specialfolder enum** 并且使用“\Downloads”仅适用于 EN-* 系统。并且_用户可以更改位置_。完整解释[获取.NET中的所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-folders-in-net) (3认同)
  • 这个答案根本就是错误的。虽然特殊文件夹“Downloads”的默认值是用户配置文件主目录下名为“Downloads”的文件夹,但用户可以轻松地将“Downloads”特殊文件夹更改为他们有权访问的任何其他位置。对于修改了“下载”特殊文件夹目标的任何用户,上述_将不起作用_。 (3认同)
  • 这会在我的机器上崩溃。我的机器有 SSD 和机械硬盘。因此,虽然用户配置文件位于 C: 上,但桌面、下载、文档、图片、音乐、视频文件夹都位于 D: 驱动器上,纯粹是为了存储空间。个人来说不太好回答。 (3认同)