SHGetFolderPath Не рекомендуется: Какая альтернатива для извлечения пути для папок Windows?

SHGetFolderPath() эта функция устарела, начиная с Windows Vista: http://msdn.microsoft.com/en-us/library/bb762181%28v=VS.85%29.aspx

Каков альтернативный способ получения пути к папке приложения в Windows?

SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, szPath)

Кроме того, почему я получаю эти ошибки при использовании этой функции:

Error   1   error C2065: 'CSIDL_COMMON_APPDATA' : undeclared identifier 

Error   2   error C3861: 'SHGetFolderPath': identifier not found

4 ответа

Решение

Альтернатива описана в документации, на которую вы ссылаетесь. А именно это SHGetKnownFolderPath,

Тем не мение, SHGetKnownFolderPath доступно только на Vista или позже. Так что, если вы используете привязку времени загрузки и запускаете программу, которая вызывает SHGetKnownFolderPath на XP эта программа не запустится. Это явно проблема, если вы хотите поддерживать XP.

Теперь вы можете перейти на связывание во время выполнения SHGetKnownFolderPath, Перед вызовом выполните проверку версии, и если функция недоступна, вернитесь к SHGetFolderPath,

Лично я бы не допустил, чтобы это осуждение чрезмерно волновало вас. Microsoft славится поддержкой обратной совместимости. Не ожидайте SHGetFolderPath исчезнуть в ближайшее время. Вы найдете это SHGetFolderPath существует в Windows 8, и я ожидаю, что она все еще будет присутствовать в любой текущей версии Windows 10 лет спустя. Мой совет - придерживаться ссылки на время загрузки и переключаться только на SHGetKnownFolderPath когда вы отказываетесь от поддержки XP.

Ваш другой вопрос, который вы задаете в редакции, это как позвонить SHGetFolderPath, Вы должны соблюдать требования, изложенные в нижней части раздела документации MSDN, который вы указали в своем вопросе. В частности, включить Shlobj.h и передать Shlobj.lib компоновщику.

Он связан прямо вверху, SHGetKnownFolderPath.

CSIDL_COMMON_APPDATA заменяется на FOLDERID_ProgramData в новом API.

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

Я уже звонила SHGetFolderPath и также включил #include <ShlObj.h> но это было в другом заголовочном файле. Решение компилировалось без каких-либо ошибок, прежде чем я добавил в него новые файлы заголовков библиотеки.

Я пытался заменить SHGetFolderPath() с SHGetKnownFolderPath() но это просто перенаправил идентификатор не найдена ошибка в SHGetKnownFolderPath,

При добавлении #include <ShlObj.h> в заголовочный файл вызывающего класса SHGetFolderPath, ошибки прекратились, и решение снова было успешно скомпилировано.

Как уже упоминалось на этой странице, позвонив SHGetFolderPath в Windows Vista или более поздней версии SHGetKnownFolderPath,

Я проверил, используя SHGetFolderPath() с Visual Studio 2015 Enterprise на ПК с Windows 10, и он скомпилирован и прекрасно работает, чтобы найти домашнюю папку текущего пользователя. На странице Центра разработки Windows на SHGetFolderPath() В функции SHGetFolderPath есть следующее примечание:

Примечание. В Windows Vista эта функция является просто оболочкой для SHGetKnownFolderPath, CSIDL значение переводится в связанный с ним KNOWNFOLDERID а потом SHGetKnownFolderPath называется. Новые приложения должны использовать известную систему папок, а не старые CSIDL система, которая поддерживается только для обратной совместимости.

Как отметил в своем ответе Дэвид Хеффман, у Microsoft есть история обратной совместимости в течение многих лет, особенно когда они могут использовать старую функцию и просто перенаправить ее на новую функцию с соответствующими аргументами. CSIDL значения, кажется, имеют соответствующий KNOWNFOLDERID значение. Смотрите эту таблицу CSIDL константы с краткими аннотациями и соответствующими KNOWNFOLDERID значение.

Пример использования этой функции приведен ниже. Это использование извлекает папку пользователя текущего пользователя (например, "C:\Users\myuser\Documents" в Windows 7) и затем добавляет имя папки в конец пути, используя PathAppend() функция.

TCHAR   achDevice[MAX_PATH];
HRESULT  hr;
// include file ShlObj.h contains list of CSIDL defines however only a subset
// are supported with Windows 7 and later.
// for the 3rd argument, hToken, can be a specified Access Token or SSID for
// a user other than the current user. Using NULL gives us the current user.
if (SUCCEEDED(hr = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, achDevice))) {
    // append a folder name to the user's Documents directory.
    // the Path Handling functions are pretty handy.
    PathAppend(achDevice, L"xxx");
}

Одна возможная ошибка - один или несколько недопустимых аргументов (hr == E_INVALIDARG). Возвращаемое значение S_OK указывает на то, что вызов выполнен успешно.

Есть несколько CSIDL константы, которые могут быть использованы для изменения результатов функции, таких как CSIDL_FLAG_CREATE используя побитовый оператор ИЛИ. Я не уверен, насколько хорошо эти операторы будут работать с Windows 7 и более поздними версиями.

Есть ограничения на поддерживаемые CSIDL константы с Windows 7 и выше. Похоже, что в сложных, удаленно смонтированных, перенаправленных и / или общих папках в Active Directory или аналогичной среде могут быть возможные проблемы, которые необходимо решить.

Смотрите также KNOWNFOLDERID, который включает в себя таблицу, которая указывает на некоторые ограничения CSIDL а также SHGetFolderPath(), Некоторые примеры из таблицы CSIDL константы, которые могут быть полезны.

CSIDL_LOCAL_APPDATA - %USERPROFILE%\AppData\Local
CSIDL_MYDOCUMENTS - %USERPROFILE%\Document
CSIDL_PERSONAL -    %USERPROFILE%\Documents
CSIDL_FONTS -       %windir%\Fonts
CSIDL_MYMUSIC -     %USERPROFILE%\Music
CSIDL_MYPICTURES -  %USERPROFILE%\Pictures
CSIDL_COMMON_APPDATA - %ALLUSERSPROFILE% (%ProgramData%, %SystemDrive%\ProgramData)
CSIDL_COMMON_DOCUMENTS -    %PUBLIC%\Documents

Кстати, Функции Обработки Пути Shell - хорошая библиотека методов для управления путями файла.

Смотрите также Где разместить общие файлы приложений для записи?

От Microsoft альтернативный вариант - SHGetKnownFolderPathhttps://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpatha.

С моей точки зрения, эти функции предназначены для c, C++ и подобных языков. Из powershell я только что прочитал реестр: PS> cd hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\ PS> dir

Здесь загляните в "Папки оболочки" и "Папки пользовательской оболочки".

кстати: это для получения значений. Я бы сказал, что это довольно безопасно. Для установки значений лучше не использовать реестр напрямую, так как это испортит вам день. Использование проводника -> свойства этих "каталогов" для их перемещения также приведет к перемещению содержимого. К сожалению, я не знаю, как использовать это в PowerShell.

Другие вопросы по тегам