Search code examples
.netenvironment-variableswindows-vistaspecial-folders

How to programmatically derive Windows Downloads folder "%USERPROFILE%/Downloads"?


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?


Solution

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