Как получить путь к CSIDL_COMMON_DOCUMENTS в .NET 3.5? - PullRequest
3 голосов
/ 23 декабря 2011

Я делаю пользовательское действие для установщика.Он должен прочитать файл, хранящийся в CSIDL_COMMON_DOCUMENTS, чтобы определить каталог установки.(Я надеюсь, что не будет проблемой изменить каталог установки в пользовательском действии, но это другой вопрос.)

Я вижу, что .NET 4 добавил CommonDocuments к Environment.SpecialFolder.К сожалению, я застрял с .NET 3.5.Какой следующий самый простой способ получить этот путь?

1 Ответ

1 голос
/ 23 декабря 2011

Самый простой способ, который я знаю, - это 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();
}

Только для вашей информации, функция SHGetFolderPath устарела с Windows Vista в пользу SHGetKnownFolderPath (команда разработчиков оболочки просто любит все это менять). Эта новая функция приносит новый набор идентификаторов; вместо значений CSIDL теперь используются значения KNOWNFOLDERID. Они рекомендуют, чтобы все новые приложения использовали новую функцию.

Но, учитывая, что вы ориентируетесь на старую версию .NET Framework и не хотите обновляться, стоит поспорить, что вам, вероятно, нет необходимости вызывать последнюю функцию API. : -)

Старый продолжает отлично работать в Windows Vista и 7, даже если он реализован внутри просто как тонкая оболочка для новой функции. Если это не удастся в Windows 8, вам придется разделить пути кода или, наконец, откусить маркер и перейти на последнюю версию .NET, которая обрабатывает все это за вас.

...