3

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

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

4

1 回答 1

1

The easiest way I know of is to P/Invoke the SHGetFolderPath function, which is very likely what the .NET Framework uses internally to retrieve the Environment.SpecialFolders values.

The definition would look like this:

[DllImport("shell32.dll"), CharSet = CharSet.Auto]
static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken,
                                  uint dwFlags, [Out] StringBuilder pszPath);

You'll also need the CSIDL_COMMON_DOCUMENTS constant. Direct from the Windows headers:

const int CSIDL_COMMON_DOCUMENTS = 0x002e;

If you want to force the creation of the folder if it does not already exist, you'll need to pass the CSIDL_FLAG_CREATE flag. That is defined as follows:

const int CSIDL_FLAG_CREATE = 0x8000;

Call it like this:

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();
}

Just for your information, the SHGetFolderPath function has been deprecated as of Windows Vista in favor of SHGetKnownFolderPath (the shell team just loves to change these things around). That new function brings with it a new set of identifiers; instead of CSIDL values, it now uses KNOWNFOLDERID values. They recommend that all new applications use the new function.

But considering that you're targeting an old version of the .NET Framework and don't want to upgrade, it's a good bet that you probably have no need to call the latest API function, either. :-)

The old one continues to work just fine in Windows Vista and 7, even if it's implemented internally merely as a thin wrapper over the new function. If it fails in Windows 8, you'll have to segregate your code paths, or finally bite the bullet and upgrade to the latest version of .NET, which handles it all for you.

于 2011-12-23T10:50:00.820 回答