0

I want to get the filepath of the user's profile picture in Windows using Python.

I've found the following approach in VB6:

Option Explicit
'KERNEL32
Private Declare Function GetVersion Lib "KERNEL32" () As Long
'SHELL32
Private Declare Function SHGetUserPicturePath Lib "SHELL32" Alias "#261" (ByVal pUserOrPicName As Long, ByVal sguppFlags As Long, ByVal pwszPicPath As Long, ByVal picPathLen As Long) As Long
Private Declare Function xp_SHGetUserPicturePath Lib "SHELL32" Alias "#233" (ByVal pUserOrPicName As Long, ByVal sguppFlags As Long, ByVal pwszPicPath As Long) As Long

Private Const SGUPP_CREATEPICTURESDIR = &H80000000

Public Function LoadUserTile() As IPictureDisp
    Dim sPath   As String

    sPath = String$(256, vbNullChar)

    Select Case (GetVersion() And &HFF)
        Case 5
            Call xp_SHGetUserPicturePath(0, SGUPP_CREATEPICTURESDIR, StrPtr(sPath))
        Case 6
            Call SHGetUserPicturePath(0, SGUPP_CREATEPICTURESDIR, StrPtr(sPath), 256)
    End Select

    sPath = Left$(sPath, InStr(1, sPath, vbNullChar) - 1)

    Set LoadUserTile = LoadPicture(sPath)
End Function

But I don't know how to translate it to Python using ctypes, as the functions used are not documented by the MSDN. I've found this alternative resource, though.

I've also tried to access this folder:

%ProgramData%\Microsoft\User Account Pictures\Guest.bmp
%ProgramData%\Microsoft\User Account Pictures\User.bmp

But there are stored the default profile pictures, not the current ones.

mllamazares
  • 7,876
  • 17
  • 61
  • 89

2 Answers2

1

Use this:

import glob
import os
# Please change the <username> to your username
search_dir = "C:\\Users\\<username>\\AppData\\Roaming\\Microsoft\\Windows\\AccountPictures\\"
files = list(filter(os.path.isfile, glob.glob(search_dir + "*")))
files.sort(key=lambda x: os.path.getmtime(x))

So, you will have a python list files which will contain the list of files in sorted by 'date of creation' order. You can access the latest account picture using files[0]

I took some reference from this article

Jatin Chauhan
  • 327
  • 1
  • 2
  • 10
1

Listing [Python.Docs]: ctypes - A foreign function library for Python.

[Airesoft.UnDoc]: SHGetUserPicturePath (and the referenced SHGetUserPicturePathEx) contains the exact needed info:

Copies the users account picture to a temporary directory and returns the path or returns various paths relating to user pictures

Syntax

HRESULT WINAPI SHGetUserPicturePath (
    LPCWSTR pwszPicOrUserName,
    DWORD sguppFlags,
    LPWSTR pwszPicPath,
    UINT picPathLen
)

Although the table at the end of the page lists Win 8.1 as the newest version, it also works on Win 10.

Notes:

  • Needless to say that being not part of the public API, it shouldn't be relied on (except maybe for demo / learning purposes), as the behavior might change or it could completely disappear. Don't use this code in production!

code00.py:

#!/usr/bin/env python

import sys
import ctypes as ct
from ctypes import wintypes as wt


SGUPP_DIRECTORY = 0x01
SGUPP_DEFAULTDIRECTORY = 0x02
SGUPP_CREATEPICTURESDIR = 0x80000000


def main(*argv):
    shell32 = ct.WinDLL("shell32.dll")
    SHGetUserPicturePathW = shell32[261]
    SHGetUserPicturePathW.argtypes = (wt.LPWSTR, wt.DWORD, wt.LPWSTR, wt.UINT)
    SHGetUserPicturePathW.restype = ct.c_long

    buf_len = 0xFF
    buf = ct.create_unicode_buffer(buf_len)
    flags = SGUPP_CREATEPICTURESDIR
    res = SHGetUserPicturePathW(None, flags, buf, buf_len)
    print("    SHGetUserPicturePathW returned {0:016X}\n    Path set to: [{1:s}]".format(res, buf.value))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")),
                                                    64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Output:

e:\Work\Dev\StackOverflow\q059927534>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 064bit on win32

    SHGetUserPicturePathW returned 0000000000000000
    Path set to: [C:\Users\cfati\AppData\Local\Temp\cfati.bmp]

Done.

Related: [SO]: Get user picture.

CristiFati
  • 38,250
  • 9
  • 50
  • 87