8

...for current user? for all users?

I'm working an a small program which needs to create links in the start menu. Currently I'm hardcoding like below, but it only works in english locales, for example it should be "Startmenü" in german. What are cleaner, more portable approaches?

OUR_STARTMENU = os.environ['ALLUSERSPROFILE'] + '\Start Menu\Programs\Our Stuff'

thank you

matt wilkie
  • 17,268
  • 24
  • 80
  • 115

3 Answers3

11

I've heard of 2 ways of doing this. First:

from win32com.shell import shell
shell.SHGetSpecialFolderPath(0,shellcon.CSIDL_COMMON_STARTMENU)

Second, using the WScript.Shell object (source : http://www.mail-archive.com/python-win32@python.org/msg00992.html):

import win32com.client
objShell = win32com.client.Dispatch("WScript.Shell")
allUserProgramsMenu = objShell.SpecialFolders("AllUsersPrograms")
userMenu = objShell.SpecialFolders("StartMenu")

Another source: http://blogs.msdn.com/saveenr/archive/2005/12/28/creating-a-start-menu-shortcut-with-powershell-and-python.aspx

Laurent
  • 3,798
  • 25
  • 22
2

Also, CSIDL_COMMON_STARTMENU is for all user startup and CSIDL_STARTMENU for current user startup.

Igor
  • 278
  • 1
  • 7
1

A friend, Luke Pinner of Environment.gov.au, gave a solution by email which uses a core module (python 2.5+). Believed to be multi-lingual as the return from the API call is unicode. Tested on Win7 with Japanese locale, and on another us-english machine by manually changing Start Menu to point to %USERPROFILE%\Startmenü

''' Get windows special folders without pythonwin
    Example:
            import specialfolders
            start_programs = specialfolders.get(specialfolders.PROGRAMS)

Code is public domain, do with it what you will. 

Luke Pinner - Environment.gov.au, 2010 February 10
'''

#Imports use _syntax to mask them from autocomplete IDE's
import ctypes as _ctypes
from ctypes.wintypes import HWND as _HWND, HANDLE as _HANDLE,DWORD as _DWORD,LPCWSTR as _LPCWSTR,MAX_PATH as _MAX_PATH, create_unicode_buffer as _cub
_SHGetFolderPath = _ctypes.windll.shell32.SHGetFolderPathW

#public special folder constants
DESKTOP=                             0
PROGRAMS=                            2
MYDOCUMENTS=                         5
FAVORITES=                           6
STARTUP=                             7
RECENT=                              8
SENDTO=                              9
STARTMENU=                          11
MYMUSIC=                            13
MYVIDEOS=                           14
NETHOOD=                            19
FONTS=                              20
TEMPLATES=                          21
ALLUSERSSTARTMENU=                  22
ALLUSERSPROGRAMS=                   23
ALLUSERSSTARTUP=                    24
ALLUSERSDESKTOP=                    25
APPLICATIONDATA=                    26
PRINTHOOD=                          27
LOCALSETTINGSAPPLICATIONDATA=       28
ALLUSERSFAVORITES=                  31
LOCALSETTINGSTEMPORARYINTERNETFILES=32
COOKIES=                            33
LOCALSETTINGSHISTORY=               34
ALLUSERSAPPLICATIONDATA=            35

def get(intFolder):
    _SHGetFolderPath.argtypes = [_HWND, _ctypes.c_int, _HANDLE, _DWORD, _LPCWSTR]
    auPathBuffer = _cub(_MAX_PATH)
    exit_code=_SHGetFolderPath(0, intFolder, 0, 0, auPathBuffer)
    return auPathBuffer.value
matt wilkie
  • 17,268
  • 24
  • 80
  • 115
  • FYI: best reference I could find for MS `SHGetFolderPath` is [here](http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181%28v=vs.85%29.aspx), which notes that it deprecated as of Vista in favour of [`SHGetKnownFolderPath`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx) – matt wilkie Oct 24 '11 at 16:36
  • A more polished answer using ctypes can be seen at https://stackoverflow.com/a/30540388/14420 – matt wilkie Aug 29 '19 at 11:42