Специальные и известные папки Windows из python (меню «Пуск», «Загрузки»,)

Как лучше всего определить путь к Windows специальные-папки и известные-папки в питоне?

Я обнаружил несколько популярных методов для SpecialFolders, также известных как CSIDL, но пока ничего простого для KNOWNFOLDERID. Поддерживается обратная совместимость, поэтому методы CSIDL по-прежнему работают, но любые специальные / известные папки, появившиеся после Windows XP, в них не перечислены. Примеры "новых" недоступных: Загрузки, Плейлисты, Программные файлы x64.

Специальные папки

Известные папки

  • ?

Оба в одном

  • ?

person matt wilkie    schedule 27.04.2015    source источник
comment
В Википедии есть их список в en.wikipedia.org/wiki/Special_folder#List_of_special_folders   -  person Marichyasana    schedule 27.04.2015
comment
Спасибо @Marichyasana, но мне нужно определить, что они из себя представляют динамически во время выполнения. Они не всегда имеют одинаковое написание (разные языки) и могут находиться в разных местах в соответствии с групповой политикой и / или другими настройками. Этот список в Википедии тоже очень неполный.   -  person matt wilkie    schedule 28.04.2015


Ответы (1)


Вы решаете эту проблему так же, как и эту: сначала вы находите документацию и, в идеале, хороший пример кода на C ++, C # или VB, затем вы выясняете, как использовать PyWin32 для выполнения того же API оболочки или IKnownFolder COM-вызовов из Python. .

В качестве обзорной документации MSDN по Известные папки говорит, что вы можете использовать новую функцию оболочки _ 2_ вместо старого SHFolderPath или SHGetFolderPath, или вы можете использовать полный _ 5_ через COM.

К сожалению, передо мной нет компьютера с Windows, и образцы загрузки MSDN не отвечают, поэтому мне придется немного гадать. Но может быть примерно так:

from win32com.shell import shell, shellcon
path = shell.SHGetKnownFolderPath(shellcon.FOLDERID_AccountPictures,
                                  0, # see KNOWN_FOLDER_FLAG
                                  0) # current user

Если shellcon не имеет значений FOLDERID, вам нужно будет найти их в _ 9_ и определите необходимые вам константы.

Если shell не имеет функции SHGetKnownFolderPath, вам придется создать экземпляр IKnownFolderManager и вызвать GetFolderByName.

Если shell даже не IKnownFolderManager… но быстрый Google показывает это был добавлен в сборку 218, так что это не будет проблемой.


Если вы предпочитаете делать это через ctypes, а не через win32com, это будет выглядеть примерно так (опять же, непроверено, потому что у меня нет окна Windows и сервер MSDN сломан):

from ctypes import windll, wintypes
from ctypes import *
from uuid import UUID

# ctypes GUID copied from MSDN sample code
class GUID(Structure):
    _fields_ = [
        ("Data1", wintypes.DWORD),
        ("Data2", wintypes.WORD),
        ("Data3", wintypes.WORD),
        ("Data4", wintypes.BYTE * 8)
    ] 

    def __init__(self, uuidstr):
        uuid = UUID(uuidstr)
        Structure.__init__(self)
        self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], rest = uuid.fields
        for i in range(2, 8):
            self.Data4[i] = rest>>(8-i-1)*8 & 0xff

FOLDERID_AccountPictures = '{008ca0b1-55b4-4c56-b8a8-4de4b299d3be}'

SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
SHGetKnownFolderPath.argtypes = [
    POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, POINTER(c_char_p)]

def get_known_folder_path(uuidstr):
    pathptr = c_wchar_p()
    guid = GUID(uuidstr)
    if SHGetKnownFolderPath(byref(guid), 0, 0, byref(pathptr)):
        raise Exception('Whatever you want here...')
    return pathptr.value
person abarnert    schedule 27.04.2015
comment
Ваша интуиция верна, win32com.shell не имеет функции SHGetKnownFolderPath, по крайней мере, на моей машине Win7 py27. Создание экземпляра IKnownFolderManager через COM выходит за рамки моего текущего понимания. В конце концов я отследил ваш ключ к shell.IID_IKnownFolderManagement (спасибо, я использовал старый pywin32 без него), но атрибут GetFolderByName не существует. Поиск в сети не дал примеров, только объявление о его доступности. Я нашел такие элементы, как shell.FOLDERID_Downloads, которые возвращают код IID, но я не смог понять, как использовать его для перехода к пути. - person matt wilkie; 28.04.2015
comment
Признаюсь в недоумении. Windows KnownFolders уже давно отсутствует, и я ожидал, что мне укажут на проторенный путь. Думаю, я был избалован тем, что большинство моих квестов на питоне на сегодняшний день были с включенными батареями. :) ... Завтра я рассмотрю пример ctypes. Может быть, это принесет мне больше плодов. (Чуть не забыл: большое спасибо за то, что дал мне что-то, над чем можно подумать и пережевать.) - person matt wilkie; 28.04.2015
comment
Вспомнил, что вчера наткнулся на этот пример ctypes, gist.github.com/mkropat/7550097 . Он похож на ваш, хотя я еще не изучил его внимательно, чтобы увидеть, является ли сходство только поверхностным. В моем быстром первоначальном тестировании он всегда возвращает значения по умолчанию вместо текущего пользователя. - person matt wilkie; 28.04.2015
comment
@mattwilkie: Эта последняя проблема может быть просто глупой ошибкой с моей стороны. Проверьте документацию, чтобы убедиться, что фактический 0 (NULL) означает текущего пользователя, а не значение по умолчанию. Есть несколько случаев, когда API-интерфейсы используют приведение 1-7 к void * для других специальных значений, и это может быть один ... - person abarnert; 28.04.2015