How to find user's Downloads folder in PowerShell?

Mark Moore 21 Reputation points
2024-01-19T06:25:17.52+00:00

There are a number of posts on the web saying to effectively concatenate the expansion of %USERPROFILE% and "\Downloads" to locate the Downloads special folder. That is horribly broken because a) it's not localized, and b) users can change the target of their special folders -- I have.

I found an archived post from Doctor Scripto titled "The Easy Way to Use PowerShell to Work with Special Folders"1 which says to use the [environment]::getfolderpath() function to obtain the path to any special folder.

Unfortunately, that method is not documented in any of the PowerShell documentation I can find. (Happy to be corrected.) From spelunking, it seems that function accepts any string that (case insensitively) matches the name of one of the .NET System.Environment.SpecialFolder enums, and returns a string value of the path to that folder.

Even more unfortunately, System.Environment.SpecialFolder does not include many of the defined special folder enums from the Windows SDK.2

Most conspicuously absent is the user Downloads folder enum (FOLDERID_Downloads).

Until .NET decides to fix its broken implementation of [environment]::GetFolderPath(), it looks like the only way to reliably find the user Downloads folder is to write some horrible PowerShell code to directly interact with the Windows API in order to:

  1. instantiate an instance of an IKnownFolderManager,
  2. call its GetFolder() method or, worse, iterate through the list of KNOWNFOLDERIDs returned by its GetFolderIds() method, and then
  3. call the IKnownFolder's GetPath() method.
  4. don't forget to correctly Release() and CoTaskMemFree() all the handles and resources to clean up.

I did find a Doctor Scripto article on how to call Windows API from PowerShell.3 And the CExplorerBrowserHostDialog::_FillViewWithKnownFolders() implementation in the ExploreBrowserCustomContents example in the Win7Samples folder of the Windows-classic-samples project up on GitHub shows how to enumerate the known special folders.4 🤮🤮

I'm hoping someone out there knows a better way to do this, or that maybe someone has done a more complete PowerShell/.Net implementation of the IKnownFolder API.

Windows
Windows
A family of Microsoft operating systems that run across personal computers, tablets, laptops, phones, internet of things devices, self-contained mixed reality headsets, large collaboration screens, and other devices.
4,770 questions
PowerShell
PowerShell
A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
2,081 questions
{count} votes

Accepted answer
  1. Sachith Lakmal 126 Reputation points
    2024-01-19T07:17:28.53+00:00

    To properly manage system resources, it’s crucial to release and free all handles and resources when they’re no longer needed. In .NET, this is typically achieved using methods such as Dispose(), Close(), or Finalize(). For COM objects, the System.Runtime.InteropServices.Marshal.ReleaseComObject() method is used. However, the specific approach may vary based on the type of resource. In the context of PowerShell, the Shell.Application COM object provides a straightforward way to retrieve the actual path of the Downloads folder, irrespective of its location. Here’s a simple illustration: $downloadsPath = (New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path This command will return the full path to the current user’s Downloads folder.

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful