代码之家  ›  专栏  ›  技术社区  ›  Maestro

如何以编程方式派生windows下载文件夹“%USERPROFILE%/downloads”?

  •  18
  • Maestro  · 技术社区  · 15 年前

    在.NET中,我们可以检索到“特殊文件夹”的路径,如文档/桌面等。今天我试图找到一种方法来获取“下载”文件夹的路径,但它似乎不够特殊。

    我知道我可以做“C:\Users\Username\Downloads”,但这似乎是一个丑陋的解决方案。那么如何使用.NET检索路径呢?

    6 回复  |  直到 5 年前
        1
  •  2
  •   Ray Brian Agnew    5 年前

    你的第一个答案的问题是,如果默认的下载目录被更改为[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);
            }
        }
    
    }   
    

    为了测试它,如果您特别想要您的个人下载目录,您可以将default标记为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);
            }
        }
    
        2
  •  26
  •   Hans Passant    8 年前

    是的,这是特别的,发现这个文件夹的名称是不可能的,直到Vista。NET仍然需要支持以前的操作系统。您可以pinvoke 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);
    
        3
  •  2
  •   Shaahin    7 年前

    试试这个:

    string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)+ @"\Downloads";
    
        4
  •  2
  •   mythz    6 年前

    这是对 accepted answer 因为IMO可以更好地实施:

    public static class KnownFolders
    {
        public static Guid Contacts = new Guid("{56784854-C6CB-462B-8169-88E350ACB882}");
        public static Guid Desktop = new Guid("{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}");
        public static Guid Documents = new Guid("{FDD39AD0-238F-46AF-ADB4-6C85480369C7}");
        public static Guid Downloads = new Guid("{374DE290-123F-4565-9164-39C4925E467B}");
        public static Guid Favorites = new Guid("{1777F761-68AD-4D8A-87BD-30B759FA33DD}");
        public static Guid Links = new Guid("{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}");
        public static Guid Music = new Guid("{4BD8D571-6D19-48D3-BE97-422220080E43}");
        public static Guid Pictures = new Guid("{33E28130-4E1E-4676-835A-98395C3BC3BB}");
        public static Guid SavedGames = new Guid("{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}");
        public static Guid SavedSearches = new Guid("{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}");
        public static Guid Videos = new Guid("{18989B1D-99B5-455B-841C-AB7C74E4DDFC}");
    
        static Dictionary<string, Guid> Map { get; } = new Dictionary<string, Guid> {
            { nameof(Contacts), Contacts },
            { nameof(Desktop), Desktop },
            { nameof(Documents), Documents },
            { nameof(Downloads), Downloads },
            { nameof(Favorites), Favorites },
            { nameof(Links), Links },
            { nameof(Music), Music },
            { nameof(Pictures), Pictures },
            { nameof(SavedGames), SavedGames },
            { nameof(SavedSearches), SavedSearches },
            { nameof(Videos), Videos },
        };
    
        public static string GetPath(string knownFolder,
            KnownFolderFlags flags = KnownFolderFlags.DontVerify, bool defaultUser = false) =>
            Map.TryGetValue(knownFolder, out var knownFolderId)
                ? GetPath(knownFolderId, flags, defaultUser)
                : ThrowUnknownFolder();
    
        public static string GetPath(Guid knownFolderId, 
            KnownFolderFlags flags=KnownFolderFlags.DontVerify, bool defaultUser=false)
        {
            if (SHGetKnownFolderPath(knownFolderId, (uint)flags, new IntPtr(defaultUser ? -1 : 0), out var outPath) >= 0)
            {
                string path = Marshal.PtrToStringUni(outPath);
                Marshal.FreeCoTaskMem(outPath);
                return path;
            }
            return ThrowUnknownFolder();
        }
    
        //[DoesNotReturn]
        static string ThrowUnknownFolder() => 
            throw new NotSupportedException("Unable to retrieve the path for known folder. It may not be available on this system.");
    
        [DllImport("Shell32.dll")]
        private static extern int SHGetKnownFolderPath(
            [MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
    }
    

    可通过以下方式调用:

    var downloadPath = KnownFolders.GetPath(KnownFolders.Downloads);
    

    或者有时使用字符串获取它更方便:

    var downloadPath = KnownFolders.GetPath(nameof(KnownFolders.Downloads));
    
        5
  •  -1
  •   Jabez    8 年前

    "C:\Users\<username>"

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

    在“访问下载”文件夹旁边,只需按以下方式组合其他路径字符串:

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

    现在,最终结果将是

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

        6
  •  -1
  •   Lorenzo Isidori    6 年前

    没那么难。如果你想得到下载文件夹目录运动模拟,只需执行以下步骤:

    2.加载表单时添加此代码:

    Special_directories.Text = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\downloads\"
    

    这将把标签文本设置为用户文件夹路径和“\downloads\”。 这就是它的样子:

    C:\users\USERFOLDER\下载\

        7
  •  -2
  •   Pratama Aditya    8 年前

    尝试:

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

    这只是个骗局,不是解决办法。

        8
  •  -4
  •   H--    11 年前

    Dim strNewPath As String = IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) + "\Downloads\"
    
    推荐文章