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

发布于 2024-09-25 08:57:48 字数 155 浏览 17 评论 0原文

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

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

In .NET, we can retrieve the paths to 'special folders', like Documents / Desktop etc. Today I tried to find a way to get the path to the 'Downloads' folder, but it's not special enough it seems.

I know I can just do 'C:\Users\Username\Downloads', but that seems an ugly solution. So how can I retrieve the path using .NET?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

檐上三寸雪 2024-10-02 08:57:48

是的,它很特别,直到 Vista 才可以发现该文件夹的名称。 .NET 仍然需要支持以前的操作系统。您可以调用 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);

Yes it is special, discovering the name of this folder didn't become possible until Vista. .NET still needs to support prior operating systems. You can pinvoke SHGetKnownFolderPath() to bypass this limitation, like this:

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);
小鸟爱天空丶 2024-10-02 08:57:48

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

}   

测试它,如果您特别想要您的个人下载目录,则将默认值标记为 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);
        }
    }

The problem of your first answer is it would give you WRONG result if the default Downloads Dir has been changed to [Download1]! The proper way to do it covering all possibilities is

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

}   

To test it, if you specifically desire your personal download dir, you flag default to 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);
        }
    }
把时间冻结 2024-10-02 08:57:48

这是接受的答案的重构,因为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));

This is a refactor of the accepted answer as IMO it could be implemented a little nicer:

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

Can be called with:

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

Or sometimes it's more convenient to fetch it using a string:

var downloadPath = KnownFolders.GetPath(nameof(KnownFolders.Downloads));
娇女薄笑 2024-10-02 08:57:48

上面 Hans Passant 的回答关于使用 SHGetKnownFolderPath (像往常一样)绝对正确。但如果您愿意,您可以引导更多 P/Invoke 功能来简化导入并使其签名更加“.NET 风格”:

  • 我们指定 CharSet = CharSet.Unicode,因为返回字符串始终是 Unicode PWSTR。没有 AW 重载,因此我们还设置 ExactSpelling = true 以防止运行时搜索此类重载。现在,我们可以将 out IntPtr path 替换为 out string path,从而使编组器自动转换字符串,包括释放内存1。这消除了我们手动调用 PtrToStringUniFreeCoTaskMem 的负担:

    公共静态字符串 GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) 抛出 new NotSupportedException();
        字符串路径;
        SHGetKnownFolderPath(参考FolderDownloads, 0, IntPtr.Zero, 输出路径);
        返回路径;
    }
    
    私人静态Guid文件夹下载=新Guid(“374DE290-123F-4565-9164-39C4925E467B”);
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    私有静态 extern int SHGetKnownFolderPath(ref Guid id, int flags,
        IntPtr 令牌,输出字符串路径);
    
  • 我们可以指定PreserveSig = false来转换失败< code>HRESULT 由方法返回到 适当抛出异常,并将“return”值替换为最后一个out参数,例如out string path

    公共静态字符串 GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) 抛出 new NotSupportedException();
        返回SHGetKnownFolderPath(参考FolderDownloads,0,IntPtr.Zero);
    }
    
    私人静态Guid文件夹下载=新Guid(“374DE290-123F-4565-9164-39C4925E467B”);
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    私有静态外部字符串 SHGetKnownFolderPath(ref Guid id, int flags,
        IntPtr 令牌);
    
  • 为了进一步简化向方法传递参数,我们可以告诉编组器自动传递 Guid 作为引用 <代码>MarshalAs(UnmanagedType.LPStruct):

    公共静态字符串 GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) 抛出 new NotSupportedException();
        返回 SHGetKnownFolderPath(FolderDownloads, 0, IntPtr.Zero);
    }
    
    私人静态Guid文件夹下载=新Guid(“374DE290-123F-4565-9164-39C4925E467B”);
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    私有静态外部字符串 SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid id、int 标志、IntPtr 令牌);
    
  • 模拟在WinAPI方法中将token参数声明为可选,我们可以指定= 0=default,并使用C# 9 的nint 而不是 IntPtr

    公共静态字符串 GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) 抛出 new NotSupportedException();
        返回 SHGetKnownFolderPath(FolderDownloads, 0);
    }
    
    私人静态Guid文件夹下载=新Guid(“374DE290-123F-4565-9164-39C4925E467B”);
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    私有静态外部字符串 SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid id、int 标志、nint 标记 = 0);
    

我提供了一个完整的示例,不仅检索 我的其他答案,并在 我的 CodeProject 文章



1 Automatic string conversion only works in this specific case. The marshaller assumes that 1) the buffer pointed to by the IntPtr was allocated with CoTaskMemAlloc before, and 2) the caller must free it. Thus it always calls CoTaskMemFree on it after conversion, which crashes if the conditions weren't met. It also requires an appropriate CharSet in the DllImport attribute, or converts strings with wrong encoding.

Hans Passant's answer above about using SHGetKnownFolderPath is (as usual) absolutely correct. But if you like, you can channel some more P/Invoke functionality to simplify the import and make its signature more ".NET-esque":

  • We specify CharSet = CharSet.Unicode since the returned string is always a Unicode PWSTR. There are no A and W overloads, thus we also set ExactSpelling = true to prevent runtime searching for such. This now allows us to replace out IntPtr path with out string path which makes the marshaller convert the string automatically, including freeing the memory1. That removes the burden put on us to manually call PtrToStringUni and FreeCoTaskMem:

    public static string GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
        string path;
        SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out path);
        return path;
    }
    
    private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int SHGetKnownFolderPath(ref Guid id, int flags,
        IntPtr token, out string path);
    
  • We can specify PreserveSig = false to convert failure HRESULTs returned by the method into appropriate thrown exceptions, and replace the "return" value with the last out parameter, e.g. out string path:

    public static string GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
        return SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero);
    }
    
    private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    private static extern string SHGetKnownFolderPath(ref Guid id, int flags,
        IntPtr token);
    
  • To further simplify passing parameters to the method, we can tell the marshaller to automatically pass the Guid as a reference with MarshalAs(UnmanagedType.LPStruct):

    public static string GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
        return SHGetKnownFolderPath(FolderDownloads, 0, IntPtr.Zero);
    }
    
    private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    private static extern string SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid id, int flags, IntPtr token);
    
  • To simulate the token parameter being declared optional in the WinAPI method, we can specify = 0 or = default, and use C# 9's new nint instead of an IntPtr:

    public static string GetDownloadsPath() {
        if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
        return SHGetKnownFolderPath(FolderDownloads, 0);
    }
    
    private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
    [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true,
        PreserveSig = false)]
    private static extern string SHGetKnownFolderPath(
        [MarshalAs(UnmanagedType.LPStruct)] Guid id, int flags, nint token = 0);
    

I've provided a complete example retrieving more than just the Downloads folder in my other answer, and go into further detail on it on my CodeProject article.



1 Automatic string conversion only works in this specific case. The marshaller assumes that 1) the buffer pointed to by the IntPtr was allocated with CoTaskMemAlloc before, and 2) the caller must free it. Thus it always calls CoTaskMemFree on it after conversion, which crashes if the conditions weren't met. It also requires an appropriate CharSet in the DllImport attribute, or converts strings with wrong encoding.

半﹌身腐败 2024-10-02 08:57:48

试试这个:

string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)+ @"\Downloads";

Try this:

string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)+ @"\Downloads";
誰認得朕 2024-10-02 08:57:48

汉斯的回答非常有效!我很欣赏这是一个非常古老的问题,但由于 .Net(无论出于何种原因)仍然没有堵塞这个功能漏洞,我想我会发布以下对 Han 答案的重构,以防有人发现它有用。

  • 添加了一些缺失的错误处理
  • 通过属性而不是方法

访问文件夹,即与其他.Net环境用法(例如Environment.CurrentDirectory)复制/粘贴片段

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace Utils
{
    public static class SpecialFolder
    {
        public static string Downloads => _downloads ??= GetDownloads();

        // workaround for missing .net feature SpecialFolder.Downloads
        // - https://stackoverflow.com/a/3795159/227110
        // - https://stackoverflow.com/questions/10667012/getting-downloads-folder-in-c
        private static string GetDownloads()
        {
            if (Environment.OSVersion.Version.Major < 6)
                throw new NotSupportedException();

            var pathPtr = IntPtr.Zero;
            try
            {
                if (SHGetKnownFolderPath(ref _folderDownloads, 0, IntPtr.Zero, out pathPtr) != 0)
                    throw new DirectoryNotFoundException();
                return Marshal.PtrToStringUni(pathPtr);
            }
            finally
            {
                Marshal.FreeCoTaskMem(pathPtr);
            }
        }

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);

        private static Guid _folderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
        private static string _downloads;
    }
}

一致。

var downloadFolder = SpecialFolder.Downloads;

Hans's answer works perfectly! And I appreciate it's a very old question, but seeing as .Net (for whatever reason) still hasn't plugged this functionality hole, I figured I'd post the below refactoring of Han's answer in case someone finds it useful.

  • added some missing error handling
  • access folder via a property instead of a method, i.e. consistent with other .Net Environment usage (e.g Environment.CurrentDirectory)

copy/paste snippet..

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace Utils
{
    public static class SpecialFolder
    {
        public static string Downloads => _downloads ??= GetDownloads();

        // workaround for missing .net feature SpecialFolder.Downloads
        // - https://stackoverflow.com/a/3795159/227110
        // - https://stackoverflow.com/questions/10667012/getting-downloads-folder-in-c
        private static string GetDownloads()
        {
            if (Environment.OSVersion.Version.Major < 6)
                throw new NotSupportedException();

            var pathPtr = IntPtr.Zero;
            try
            {
                if (SHGetKnownFolderPath(ref _folderDownloads, 0, IntPtr.Zero, out pathPtr) != 0)
                    throw new DirectoryNotFoundException();
                return Marshal.PtrToStringUni(pathPtr);
            }
            finally
            {
                Marshal.FreeCoTaskMem(pathPtr);
            }
        }

        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);

        private static Guid _folderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
        private static string _downloads;
    }
}

usage

var downloadFolder = SpecialFolder.Downloads;
ㄖ落Θ余辉 2024-10-02 08:57:48

这是我获取 SavedGames 路径的最简单的解决方案。
要获取其他文件夹的路径,您必须相应地更改 GUID。

public static string GetSavedGamesPath()
{
    SHGetKnownFolderPath(new Guid("{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}"), 0x00004000, new IntPtr(0), out var PathPointer);
    var Result = Marshal.PtrToStringUni(PathPointer);
    Marshal.FreeCoTaskMem(PathPointer);

    return Result;
}

[DllImport("Shell32.dll")]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);

This is my simplest possible solution for getting the SavedGames path.
For getting the path of other folders, you must change the GUID accordingly.

public static string GetSavedGamesPath()
{
    SHGetKnownFolderPath(new Guid("{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}"), 0x00004000, new IntPtr(0), out var PathPointer);
    var Result = Marshal.PtrToStringUni(PathPointer);
    Marshal.FreeCoTaskMem(PathPointer);

    return Result;
}

[DllImport("Shell32.dll")]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
难如初 2024-10-02 08:57:48

我使用了下面的代码,它适用于 Windows 7 及更高版本的 .net 4.6。
下面的代码给出了用户配置文件文件夹路径 -> "C:\Users\<用户名>"

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

接下来要访问下载文件夹,只需组合其他路径字符串,如下所示:

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

现在,最终结果将是

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

希望它可以为将来的人节省时间。

I used the below code and it works for .net 4.6 with Windows 7 and above.
The below code gives the user profile folder path -> "C:\Users\<username>"

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

Next to access the downloads folder just combine additional path strings as below:

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

Now, the final result will be

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

Hope it saves time for someone in the future.

捎一片雪花 2024-10-02 08:57:48

这并不难。如果你想获取vb.net中的downloads文件夹目录,只需按照下列步骤操作:

1.添加一个名为Special_Direcories的标签。

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

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

这会将标签文本设置为用户文件夹路径和“\downloads\”。
它将如下所示:

C:\users\USERFOLDER\downloads\

It's not that hard. If you want to get the downloads folder directory in vb.net, Just follow these steps:

1.Add a label named Special_Direcories.

2.Add this code when the form loaded:

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

This will set the label text as the user folder path and "\downloads\".
This is how it will look like:

C:\users\USERFOLDER\downloads\

若相惜即相离 2024-10-02 08:57:48

尝试:

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

这只是一个技巧,而不是解决方案。

try:

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

its just a trick , not solution .

空名 2024-10-02 08:57:48

对于VB,尝试...

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

For VB, try...

Dim strNewPath As String = IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) + "\Downloads\"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文