Reputation: 10959
On my machine, it's here:
string downloadsPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Downloads");
But on a colleagues machine, this folder doesnt exist, and his Downloads folder is in his 'My Documents' folder. We are both on Windows 7*.
*Edit: in fact, it turns out he was not running the app on his own machine but a Windows Server 2003 machine.
Upvotes: 28
Views: 44868
Reputation: 141
You can use the Windows API Code Pack for Microsoft .NET Framework.
Reference: Microsoft.WindowsAPICodePack.Shell.dll
Need the following namespace:
using Microsoft.WindowsAPICodePack.Shell;
Simple usage:
string downloadsPath = KnownFolders.Downloads.Path;
Upvotes: 14
Reputation: 3716
The VB.Net function that I use is following
<DllImport("shell32.dll")>
Private Function SHGetKnownFolderPath _
(<MarshalAs(UnmanagedType.LPStruct)> ByVal rfid As Guid _
, ByVal dwFlags As UInt32 _
, ByVal hToken As IntPtr _
, ByRef pszPath As IntPtr
) As Int32
End Function
Public Function GetDownloadsFolder() As String
Dim Result As String = ""
Dim ppszPath As IntPtr
Dim gGuid As Guid = New Guid("{374DE290-123F-4565-9164-39C4925E467B}")
If SHGetKnownFolderPath(gGuid, 0, 0, ppszPath) = 0 Then
Result = Marshal.PtrToStringUni(ppszPath)
Marshal.FreeCoTaskMem(ppszPath)
End If
'as recommended by Ray (see comments below)
Marshal.FreeCoTaskMem(ppszPath)
Return Result
End Function
In my program, I call it to move some CSV files in another folder.
Dim sDownloadFolder = GetDownloadsFolder()
Dim di = New DirectoryInfo(sDownloadFolder)
'Move all CSV files that begin with BE in specific folder
'that has been defined in a CONFIG file (variable: sExtractPath
For Each fi As FileInfo In di.GetFiles("BE*.csv")
Dim sFilename = sExtractPath & "\" & fi.Name
File.Move(fi.FullName, sFilename)
Next
Upvotes: 0
Reputation: 612814
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.
Upvotes: 30