我正在为安装程序进行自定义操作。它必须读取存储在其中的文件CSIDL_COMMON_DOCUMENTS
以确定安装目录。(我希望在自定义操作中更改安装目录不会成为问题,但这是一个不同的问题。)
我看到 .NET 4 添加CommonDocuments
到Environment.SpecialFolder
. 不幸的是,我坚持使用 .NET 3.5。获得这条路径的下一个最简单的方法是什么?
我正在为安装程序进行自定义操作。它必须读取存储在其中的文件CSIDL_COMMON_DOCUMENTS
以确定安装目录。(我希望在自定义操作中更改安装目录不会成为问题,但这是一个不同的问题。)
我看到 .NET 4 添加CommonDocuments
到Environment.SpecialFolder
. 不幸的是,我坚持使用 .NET 3.5。获得这条路径的下一个最简单的方法是什么?
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.