I am making a custom action for an installer. It must read a file stored in CSIDL_COMMON_DOCUMENTS
to determine the install directory. (I'm hoping it won't be an issue to change the install directory in a custom action, but that's a different question.)
I see that .NET 4 added CommonDocuments
to Environment.SpecialFolder
. Unfortunately, I'm stuck with .NET 3.5. What's the next easiest way to get this path?
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.
来源:https://stackoverflow.com/questions/8610787/how-to-get-the-path-to-csidl-common-documents-in-net-3-5