我知道的最简单的方法是 P/Invoke SHGetFolderPath function,这很可能是 .NET Framework 在内部用来检索 Environment.SpecialFolders 值的方法。
定义如下所示:
[DllImport("shell32.dll"), CharSet = CharSet.Auto]
static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken,
uint dwFlags, [Out] StringBuilder pszPath);
您还需要CSIDL_COMMON_DOCUMENTS 常量。直接来自 Windows 标头:
const int CSIDL_COMMON_DOCUMENTS = 0x002e;
如果您想强制在文件夹不存在的情况下创建该文件夹,您需要传递CSIDL_FLAG_CREATE 标志。定义如下:
const int CSIDL_FLAG_CREATE = 0x8000;
这样称呼它:
public static string GetCommonDocumentsFolder()
{
StringBuilder sb = new StringBuilder();
int retVal = SHGetFolderPath(IntPtr.Zero,
CSIDL_COMMON_DOCUMENTS | CSIDL_FLAG_CREATE,
IntPtr.Zero,
0,
sb);
Debug.Assert(retVal >= 0); // assert that the function call succeeded
return sb.ToString();
}
仅供参考,SHGetFolderPath 函数在 Windows Vista 中已被弃用,取而代之的是 SHGetKnownFolderPath(shell 团队只是喜欢改变这些东西)。这个新功能带来了一组新的标识符;它现在使用 KNOWNFOLDERID 值,而不是 CSIDL 值。他们建议所有新应用程序都使用新功能。
但考虑到您的目标是旧版本的 .NET Framework 并且不想升级,您可能也不需要调用最新的 API 函数,这是一个不错的选择。 :-)
旧版本在 Windows Vista 和 7 中仍然可以正常工作,即使它只是在内部实现为新功能的薄包装。如果它在 Windows 8 中失败,您将不得不隔离代码路径,或者最后硬着头皮升级到最新版本的 .NET,它会为您处理这一切。