2012-05-19 56 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,當我可以從註冊表中讀取值;) –