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

3

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

我发现.NET 4将CommonDocuments添加到Environment.SpecialFolder中。不幸的是,我被困在.NET 3.5中。有什么下一个最简单的方法来获取此路径吗?


可能是下载文件夹:不够特殊?的重复问题。 - Hans Passant
1个回答

1

我知道的最简单的方法是使用P/Invoke SHGetFolderPath函数,这很可能是.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();
}

仅供参考,自Windows Vista起,SHGetFolderPath函数已被弃用,取而代之的是SHGetKnownFolderPath(外壳团队喜欢改变这些东西)。新函数带来了一组新的标识符;现在它使用KNOWNFOLDERID值,而不是CSIDL值。他们建议所有新应用程序使用新函数。

但考虑到您正在针对旧版本的.NET Framework并且不想升级,您可能根本没有必要调用最新的API函数。 :-)

旧函数在Windows Vista和7中仍然可以正常工作,即使它在内部实现只是新函数的薄包装器。如果在Windows 8中失败,则必须隔离代码路径,或最终咬紧牙关升级到最新版本的.NET,它会为您处理所有内容。


4
你的代码破坏了垃圾回收堆。将字符串生成器的容量初始化为259个字符。 - Hans Passant
1
有趣的是,System.Environment.GetFolderPath 调用了 Win32Native.SHGetFolderPath,但在 .NET FW 4.0 中没有 Win32Native.SHGetKnownFolderPath - Jeroen Wiert Pluimers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接