在 .NET 中,我们可以检索“特殊文件夹”的路径,例如 Documents / Desktop 等。今天我试图找到一种方法来获取“下载”文件夹的路径,但它似乎不够特别。
我知道我可以只执行“C:\Users\Username\Downloads”,但这似乎是一个丑陋的解决方案。那么如何使用 .NET 检索路径?
在 .NET 中,我们可以检索“特殊文件夹”的路径,例如 Documents / Desktop 等。今天我试图找到一种方法来获取“下载”文件夹的路径,但它似乎不够特别。
我知道我可以只执行“C:\Users\Username\Downloads”,但这似乎是一个丑陋的解决方案。那么如何使用 .NET 检索路径?
是的,它很特别,直到 Vista 才可能发现这个文件夹的名称。.NET 仍然需要支持以前的操作系统。您可以 pinvoke SHGetKnownFolderPath() 以绕过此限制,如下所示:
using System.Runtime.InteropServices;
...
public static string GetDownloadsPath() {
if (Environment.OSVersion.Version.Major < 6) throw new NotSupportedException();
IntPtr pathPtr = IntPtr.Zero;
try {
SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out pathPtr);
return Marshal.PtrToStringUni(pathPtr);
}
finally {
Marshal.FreeCoTaskMem(pathPtr);
}
}
private static Guid FolderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);
您的第一个答案的问题是,如果默认下载目录已更改为 [Download1],它会给您错误的结果!涵盖所有可能性的正确方法是
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);
}
}
}
为了测试它,如果你特别想要你的个人下载目录,你将默认标记为 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);
}
}
试试这个:
string path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)+ @"\Downloads";
这是对已接受答案的重构,因为 IMO 可以更好地实现它:
public static class KnownFolders
{
public static Guid Contacts = new Guid("{56784854-C6CB-462B-8169-88E350ACB882}");
public static Guid Desktop = new Guid("{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}");
public static Guid Documents = new Guid("{FDD39AD0-238F-46AF-ADB4-6C85480369C7}");
public static Guid Downloads = new Guid("{374DE290-123F-4565-9164-39C4925E467B}");
public static Guid Favorites = new Guid("{1777F761-68AD-4D8A-87BD-30B759FA33DD}");
public static Guid Links = new Guid("{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}");
public static Guid Music = new Guid("{4BD8D571-6D19-48D3-BE97-422220080E43}");
public static Guid Pictures = new Guid("{33E28130-4E1E-4676-835A-98395C3BC3BB}");
public static Guid SavedGames = new Guid("{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}");
public static Guid SavedSearches = new Guid("{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}");
public static Guid Videos = new Guid("{18989B1D-99B5-455B-841C-AB7C74E4DDFC}");
static Dictionary<string, Guid> Map { get; } = new Dictionary<string, Guid> {
{ nameof(Contacts), Contacts },
{ nameof(Desktop), Desktop },
{ nameof(Documents), Documents },
{ nameof(Downloads), Downloads },
{ nameof(Favorites), Favorites },
{ nameof(Links), Links },
{ nameof(Music), Music },
{ nameof(Pictures), Pictures },
{ nameof(SavedGames), SavedGames },
{ nameof(SavedSearches), SavedSearches },
{ nameof(Videos), Videos },
};
public static string GetPath(string knownFolder,
KnownFolderFlags flags = KnownFolderFlags.DontVerify, bool defaultUser = false) =>
Map.TryGetValue(knownFolder, out var knownFolderId)
? GetPath(knownFolderId, flags, defaultUser)
: ThrowUnknownFolder();
public static string GetPath(Guid knownFolderId,
KnownFolderFlags flags=KnownFolderFlags.DontVerify, bool defaultUser=false)
{
if (SHGetKnownFolderPath(knownFolderId, (uint)flags, new IntPtr(defaultUser ? -1 : 0), out var outPath) >= 0)
{
string path = Marshal.PtrToStringUni(outPath);
Marshal.FreeCoTaskMem(outPath);
return path;
}
return ThrowUnknownFolder();
}
//[DoesNotReturn]
static string ThrowUnknownFolder() =>
throw new NotSupportedException("Unable to retrieve the path for known folder. It may not be available on this system.");
[DllImport("Shell32.dll")]
private static extern int SHGetKnownFolderPath(
[MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
}
可以调用:
var downloadPath = KnownFolders.GetPath(KnownFolders.Downloads);
或者有时使用字符串获取它更方便:
var downloadPath = KnownFolders.GetPath(nameof(KnownFolders.Downloads));
汉斯的回答完美!我很欣赏这是一个非常古老的问题,但是看到.Net(无论出于何种原因)仍然没有填补这个功能漏洞,我想我会发布下面对 Han 的答案的重构,以防有人发现它有用。
复制/粘贴片段..
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Utils
{
public static class SpecialFolder
{
public static string Downloads => _downloads ??= GetDownloads();
// workaround for missing .net feature SpecialFolder.Downloads
// - https://stackoverflow.com/a/3795159/227110
// - https://stackoverflow.com/questions/10667012/getting-downloads-folder-in-c
private static string GetDownloads()
{
if (Environment.OSVersion.Version.Major < 6)
throw new NotSupportedException();
var pathPtr = IntPtr.Zero;
try
{
if (SHGetKnownFolderPath(ref _folderDownloads, 0, IntPtr.Zero, out pathPtr) != 0)
throw new DirectoryNotFoundException();
return Marshal.PtrToStringUni(pathPtr);
}
finally
{
Marshal.FreeCoTaskMem(pathPtr);
}
}
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int SHGetKnownFolderPath(ref Guid id, int flags, IntPtr token, out IntPtr path);
private static Guid _folderDownloads = new Guid("374DE290-123F-4565-9164-39C4925E467B");
private static string _downloads;
}
}
用法
var downloadFolder = SpecialFolder.Downloads;
这是获取 SavedGames 路径的最简单的可能解决方案。要获取其他文件夹的路径,您必须相应地更改 GUID。
public static string GetSavedGamesPath()
{
SHGetKnownFolderPath(new Guid("{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}"), 0x00004000, new IntPtr(0), out var PathPointer);
var Result = Marshal.PtrToStringUni(PathPointer);
Marshal.FreeCoTaskMem(PathPointer);
return Result;
}
[DllImport("Shell32.dll")]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
我使用了下面的代码,它适用于 Windows 7 及更高版本的 .net 4.6。下面的代码给出了用户配置文件文件夹路径->"C:\Users\<username>"
string userProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
下一步要访问下载文件夹,只需组合其他路径字符串,如下所示:
string DownloadsFolder = userProfileFolder + "\\Downloads\\";
现在,最终结果将是
"C:\Users\<username>\Downloads\"
希望它为将来的人节省时间。
这并不难。如果要获取 vb.net 中的下载文件夹目录,只需按照以下步骤操作:
1.添加一个名为 Special_Direcories 的标签。
2.加载表单时添加此代码:
Special_directories.Text = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) & "\downloads\"
这会将标签文本设置为用户文件夹路径和“\downloads\”。这是它的样子:
C:\用户\用户文件夹\下载\
尝试:
Dim Dd As String = Environment.GetFolderPath(Environment.SpecialFolder.Favorites)
Dim downloD As String = Dd.Replace("Favorites", "Downloads")
txt1.text = downLoD
它只是一个技巧,而不是解决方案。
对于 VB,请尝试...
Dim strNewPath As String = IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)) + "\Downloads\"