Getting Downloads Folder in C#

Getting Downloads Folder in C#?

The Downloads folder is a so called "known" folder, together with Documents, Videos, and others.

Do NOT:

  • combine hardcoded path segments to retrieve known folder paths
  • assume known folders are children of the user folder
  • abuse a long deprecated registry key storing outdated paths

Known folders can be redirected anywhere in their property sheets. I've gone into more detail on this several years ago in my CodeProject article.

Do:

  • use the WinAPI method SHGetKnownFolderPath as it is the intended and only correct method to retrieve those paths.

You can p/invoke it as follows (I've provided only a few GUIDs which cover the new user folders):

public enum KnownFolder
{
Contacts,
Downloads,
Favorites,
Links,
SavedGames,
SavedSearches
}

public static class KnownFolders
{
private static readonly Dictionary<KnownFolder, Guid> _guids = new()
{
[KnownFolder.Contacts] = new("56784854-C6CB-462B-8169-88E350ACB882"),
[KnownFolder.Downloads] = new("374DE290-123F-4565-9164-39C4925E467B"),
[KnownFolder.Favorites] = new("1777F761-68AD-4D8A-87BD-30B759FA33DD"),
[KnownFolder.Links] = new("BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968"),
[KnownFolder.SavedGames] = new("4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4"),
[KnownFolder.SavedSearches] = new("7D1D3A04-DEBB-4115-95CF-2F29DA2920DA")
};

public static string GetPath(KnownFolder knownFolder)
{
return SHGetKnownFolderPath(_guids[knownFolder], 0);
}

[DllImport("shell32",
CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
private static extern string SHGetKnownFolderPath(
[MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags,
nint hToken = 0);
}

Here's an example of retrieving the path of the Downloads folder:

string downloadsPath = KnownFolders.GetPath(KnownFolder.Downloads);
Console.WriteLine($"Downloads folder path: {downloadsPath}");

NuGet Package

If you don't want to p/invoke yourself, have a look at my NuGet package (note that the usage is different, please check its README).

How do I determine the Windows 'Download folder' path?

Windows does not define a CSIDL for the Downloads folder and it is not available through the Environment.SpecialFolder enumeration.

However, the new Vista Known Folder API does define it with the ID of FOLDERID_Downloads. Probably the easiest way to obtain the actual value is to P/invoke SHGetKnownFolderPath.

public static class KnownFolder
{
public static readonly Guid Downloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
}

[DllImport("shell32.dll", CharSet=CharSet.Unicode)]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out string pszPath);

static void Main(string[] args)
{
string downloads;
SHGetKnownFolderPath(KnownFolder.Downloads, 0, IntPtr.Zero, out downloads);
Console.WriteLine(downloads);
}

Note that the P/invoke given on pinvoke.net is incorrect since it fails to use Unicode character set. Also I have taken advantage of the fact that this API returns memory allocated by the COM allocator. The default marshalling of the P/invoke above is to free the returned memory with CoTaskMemFree which is perfect for our needs.

Be careful that this is a Vista and up API and do not attempt to call it on XP/2003 or lower.

UWP - Get path to user download folder

Is that what you need?

string localfolder = ApplicationData.Current.LocalFolder.Path;
var array = localfolder.Split('\\');
var username = array[2];
string downloads = @"C:\Users\" + username + @"\Downloads";

This will result

C:\Users\username\Downloads

How to find browser download folder path

IE 11: default it will go to %homedrive%%homepath%\downloads or %userprofile%\downloads - result is the same. If its not default there will be a REG_SZ value with name 'Default Download Directory' in key 'HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main'

EDIT:

String path = String.Empty;
RegistryKey rKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Internet Explorer\Main");
if (rKey != null)
path = (String)rKey.GetValue("Default Download Directory");
if (String.IsNullOrEmpty(path))
path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\\downloads";

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

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

Get default download location set by the user for his PC

You can not get the DownloadsFolder's path that the user set on the device directly. You can only get the download folder's path by the StorageFile or StorageFolder's Path property where you created them in the DownloadsFolder.

You can do a trick to get the DownloadsFolder's path by the steps: Create a file in the DownloadsFolder => Get the file's path and save the path => Delete the file.

private async Task<string> GetDownloadsFolderPath()
{
StorageFile newFile = await DownloadsFolder.CreateFileAsync("mytestfile");
if (newFile != null)
{
//You maybe need to operate the DownloadFolderPath string to subtract the folder name of your app.
string DownloadFolderPath = newFile.Path;
await newFile.DeleteAsync();
return DownloadFolderPath;
}
else
{
return "There is an error to get path";
}
}


Related Topics



Leave a reply



Submit