如何以编程方式派生 Windows 下载文件夹“%USERPROFILE%/Downloads”?
在.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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
是的,它很特别,直到 Vista 才可以发现该文件夹的名称。 .NET 仍然需要支持以前的操作系统。您可以调用 SHGetKnownFolderPath() 来绕过此限制,如下所示:
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:
您的第一个答案的问题是,如果默认下载目录已更改为 [Download1],它会给您错误的结果!覆盖所有可能性的正确方法是
测试它,如果您特别想要您的个人下载目录,则将默认值标记为 false -->
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
To test it, if you specifically desire your personal download dir, you flag default to false -->
这是接受的答案的重构,因为IMO它可以实现得更好一点:
可以通过以下方式调用:
或者有时它是使用字符串获取它更方便:
This is a refactor of the accepted answer as IMO it could be implemented a little nicer:
Can be called with:
Or sometimes it's more convenient to fetch it using a string:
上面 Hans Passant 的回答关于使用
SHGetKnownFolderPath
(像往常一样)绝对正确。但如果您愿意,您可以引导更多 P/Invoke 功能来简化导入并使其签名更加“.NET 风格”:我们指定
CharSet = CharSet.Unicode
,因为返回字符串始终是 UnicodePWSTR
。没有A
和W
重载,因此我们还设置ExactSpelling = true
以防止运行时搜索此类重载。现在,我们可以将out IntPtr path
替换为out string path
,从而使编组器自动转换字符串,包括释放内存1。这消除了我们手动调用PtrToStringUni
和FreeCoTaskMem
的负担:我们可以指定
PreserveSig = false
来转换失败< code>HRESULT 由方法返回到 适当抛出异常,并将“return”值替换为最后一个out
参数,例如out string path
:为了进一步简化向方法传递参数,我们可以告诉编组器自动传递
Guid
作为引用 <代码>MarshalAs(UnmanagedType.LPStruct):模拟在WinAPI方法中将
token
参数声明为可选
,我们可以指定= 0
或=default
,并使用C# 9 的新nint 而不是
IntPtr
:
我提供了一个完整的示例,不仅检索 我的其他答案,并在 我的 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 UnicodePWSTR
. There are noA
andW
overloads, thus we also setExactSpelling = true
to prevent runtime searching for such. This now allows us to replaceout IntPtr path
without string path
which makes the marshaller convert the string automatically, including freeing the memory1. That removes the burden put on us to manually callPtrToStringUni
andFreeCoTaskMem
:We can specify
PreserveSig = false
to convert failureHRESULT
s returned by the method into appropriate thrown exceptions, and replace the "return" value with the lastout
parameter, e.g.out string path
:To further simplify passing parameters to the method, we can tell the marshaller to automatically pass the
Guid
as a reference withMarshalAs(UnmanagedType.LPStruct)
:To simulate the
token
parameter being declaredoptional
in the WinAPI method, we can specify= 0
or= default
, and use C# 9's newnint
instead of anIntPtr
: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.
试试这个:
Try this:
汉斯的回答非常有效!我很欣赏这是一个非常古老的问题,但由于 .Net(无论出于何种原因)仍然没有堵塞这个功能漏洞,我想我会发布以下对 Han 答案的重构,以防有人发现它有用。
访问文件夹,即与其他.Net环境用法(例如Environment.CurrentDirectory)复制/粘贴片段
一致。
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.
copy/paste snippet..
usage
这是我获取 SavedGames 路径的最简单的解决方案。
要获取其他文件夹的路径,您必须相应地更改 GUID。
This is my simplest possible solution for getting the SavedGames path.
For getting the path of other folders, you must change the GUID accordingly.
我使用了下面的代码,它适用于 Windows 7 及更高版本的 .net 4.6。
下面的代码给出了用户配置文件文件夹路径 ->
"C:\Users\<用户名>"
接下来要访问下载文件夹,只需组合其他路径字符串,如下所示:
现在,最终结果将是
希望它可以为将来的人节省时间。
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>"
Next to access the downloads folder just combine additional path strings as below:
Now, the final result will be
Hope it saves time for someone in the future.
这并不难。如果你想获取vb.net中的downloads文件夹目录,只需按照下列步骤操作:
1.添加一个名为Special_Direcories的标签。
2.加载表单时添加此代码:
这会将标签文本设置为用户文件夹路径和“\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:
This will set the label text as the user folder path and "\downloads\".
This is how it will look like:
尝试:
这只是一个技巧,而不是解决方案。
try:
its just a trick , not solution .
对于VB,尝试...
For VB, try...