c# - 如何在 .NET 3.5 中获取 CSIDL_COMMON_DOCUMENTS 的路径?

标签 c# .net windows winapi special-folders

我正在为安装程序执行自定义操作。它必须读取存储在 CSIDL_COMMON_DOCUMENTS 中的文件以确定安装目录。 (我希望在自定义操作中更改安装目录不会成为问题,但这是另一个问题。)

我看到 .NET 4 添加了 CommonDocumentsEnvironment.SpecialFolder。不幸的是,我坚持使用 .NET 3.5。获得这条路径的下一个最简单的方法是什么?

最佳答案

我知道的最简单的方法是 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 header :

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,它会为您处理这一切。

关于c# - 如何在 .NET 3.5 中获取 CSIDL_COMMON_DOCUMENTS 的路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8610787/

相关文章:

c# - 捕捉和重新抛出 .NET 异常的最佳实践

c# - Azure CloudBlobContainer.ListBlobs

c# - Context.GetExternalFilesDir() 不接受 null

c# - 如何将服务注入(inject)AutoMapper?

c# - 在 ef 中将对象列表添加到上下文

c# - 使用 Task.StartNew 时指定线程的名称

c++ - 如何使用 C++ 独立 ASIO 库

c++ - 如何删除输入的字母/字符串或任何输入

.net - Tidy.NET 的替代品?

ruby - linux 类似于 windows shell 中的行为-运行没有 "ruby"附加到命令的 ruby​​?