2012-05-19 52 views
27

我已经做了一些代码,将搜索目录并在列表框中显示文件。在C#中获取下载文件夹?

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那么,当人们把我的软件,有名字并不猎人......那么我如何让它到达任何用户的下载文件夹?

+0

也许使用'Environment.SpecialFolder' ** **枚举?你试过吗?path = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Personal)); path = Path.Combine(path,“Downloads”);'? – Kiquenet

回答

66

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

还有其他方法可以获得类似的结果,这些结果看起来很有前途,但最终只会在特定系统上出现完全错误的路径(例如,合并或硬编码路径的部分或滥用旧的注册表项)。其原因在于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) 
    { 
     IntPtr outPath; 
     int result = SHGetKnownFolderPath(new Guid(_knownFolderGuids[(int)knownFolder]), 
      (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); 
     } 
    } 

    [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上发现上面链接的文章。)

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

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

例如,只需拨打KnownFolders.GetPath()您要查询哪些路径的文件夹的KnownFolder枚举值。

NuGet包

如果你不想经历这一切hazzle,只需安装我最近创建了我的NuGet包。这里是project site,这里是gallery link(请注意,使用情况是不同的和抛光,请参阅项目网站上的使用部分以获取更多信息)。

+1

我刚刚尝试从codeproject网站(完整)的解决方案,它的工作原理 - 谢谢。你有没有考虑将其包装在nuget包中? –

+1

我还没有写NuGet软件包,我很少使用他们自己,但它可能会是一个有趣的教训,教我自己创建这些软件包。我只是不知道现在什么时候可以开始。 –

+0

好的,那很好。我一直都在使用它们 - 这是管理其他代码片断(安装,版本管理等)依赖的好方法。如果你有一天接受了挑战并且生成了一个nuget包,那么你是否需要更新这个答案和你的codeproject网站以及包的链接? - 那么我们希望能够找到它;) –

1
+0

等待,当我把它放在我的代码中,我得到一个错误:*找不到路径的一部分'C:\ Users \ Hunter \ Documents \ Visual Studio 2010 \ Projects \ Setup Mover2 \ Setup Mover2 \ bin \ Debug \ UserProfile \ Downloads \'。* –

+2

Environment.GetFolderPath(Environment.SpecialFolder.UserProfile))+“\ Downloads”; //我的错,对不起 – Marduk

+0

@Marduk请删除您的评论,因为他们提供的解决方案只适用于英文系统,甚至只有其中的一部分。 –

0

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

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

+0

恕我直言,更好,删除答案,因为没有用。不好的答案,因为“重新发明轮子”。 *** App.config ***不需要,只需** WinAPI ** [在.NET中获取所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-文件夹在网) – Kiquenet

6

最简单的方法是:

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

该密钥包含一个名为***“!的不祥密钥!不要使用此注册表项“***和值***”使用SHGetFolderPath或SHGetKnownFolderPath函数代替“*** 关键在于Microsoft开发人员Raymond Chen”Microsoft的Chuck Norris“ [为什么在注册表中有'!不要使用此注册表项'的信息?](https://blogs.msdn.microsoft.com/oldnewthing/20110322-00/?p=11163) [The long and sad故事的壳文件夹键](https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=41973/) – Kiquenet

+0

***“!不要使用此注册表项”*** [获取在.NET中的所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-folders-in-net) – Kiquenet

0

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

+2

这是一个只有answser的代码,我们期待更多一点技术说明:这将会突破国际版的windows。在这个问题上接受的答案是正确的方式来做到这一点,将在所有版本的Windows上工作。 – rene

+1

恕我直言,更好,删除答案,因为没有用。不好的答案,因为*下载*是** NOT值特殊文件夹枚举**并使用“\ Downloads”仅适用于EN- *系统。 _user可以更改location_。完整解释[在.NET中获取所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-folders-in-net) – Kiquenet

+0

这个答案根本不对。虽然特殊文件夹“Downloads”的_default_值是用户配置文件主目录下名为“Downloads”的文件夹,但用户将“Downloads”特殊文件夹更改为其有权访问的任何其他位置是微不足道的。对于修改了“下载”特殊文件夹的目标的任何用户,上述_将无法工作。 –

2

跨平台版本:

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

该键包含一个不祥的键名称***“!不要使用此注册表项***”和值***“使用SHGetFolderPath或SHGetKnownFolderPath函数代替*** 关键放在那里由微软开发人员雷蒙德陈,“微软的查克诺里斯”。 [为什么在注册表中有消息'!请勿使用此注册表项?](https://blogs.msdn.microsoft.com/oldnewthing/20110322-00/?p=11163) [The外壳文件夹键长而悲伤的故事](https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=41973/) – Kiquenet

+0

***“!不要使用此注册表项”** * [在.NET中获取所有“特殊文件夹”](https://www.codeproject.com/articles/878605/getting-all-special-folders-in-net) – Kiquenet

+0

@Kiquenet:做“禁止”的事情使它所有更有趣;)但他从来没有解释为什么我应该调用SHGetKnownFolderPath,当我可以从注册表中读取值;) –