winshell

Certain aspects of the Windows user interface are grouped by Microsoft as Shell functions. These include the Desktop, shortcut icons, special folders (such as My Documents) and a few other things. These are mostly available via the shell module of the win32all extensions, but whenever I need to use them, I've forgotten the various constants and so on.

Several of the shell items have two variants: personal and common, or User and All Users. These refer to systems with profiles in use: anything from NT upwards, and 9x with Profiles turned on. Where relevant, the Personal/User version refers to that owned by the logged-on user and visible only to that user; the Common/All Users version refers to that maintained by an Administrator and visible to all users of the system.

Copyright & License?

Installing It

Unzip winshellxx.zip to somewhere temporary and then just
python setup.py install
as usual.

Usage

There are three useful bits inside this module: the interface to desktop shortcuts, the interface to the various user & system folders (My Documents, Application Data, &c.), and the interface to the structured storage which you find in Word documents and so on.

Desktop Shortcuts

Strictly, these shortcuts needn't be on the desktop. As you see from the example below, you have to tell the function where to put the resulting shortcut in the [Path] parameter. The [Target] parameter determines what the shortcut will run, while [Icon] represents an offset into an executable's icon resources.

import winshell

winshell.CreateShortcut (
  Path=os.path.join (winshell.desktop (), "PythonI.lnk"),
  Target=r"c:\python22\python.exe",
  Icon=(r"c:\python22\python.exe", 0),
  Description="Python Interpreter"
)

User and System folders

When it comes to identifying where to put and find information that is specific to users on Win32 systems, the only safe thing to do is to ask Windows where the user-specific folders are. That way you don't have to work out whether you're running on Win9x or some NT-derivative, whether you're using profiles or not, whether you're logged on or not.

winshell offers values for Desktop, Start menu, Startup, Favourites, Recent Docs, and Application Data. Where it applies, both a user-specific and an all-users version are available. The all-users version of, say, the desktop is returned by setting the common flag to 1.

import winshell

print 'Desktop =>', winshell.desktop ()
print 'Common Desktop =>', winshell.desktop (1)
print 'Application Data =>', winshell.application_data ()
print 'Common Application Data =>', winshell.application_data (1)
print 'Bookmarks =>', winshell.bookmarks ()
print 'Common Bookmarks =>', winshell.bookmarks (1)
print 'Start Menu =>', winshell.start_menu ()
print 'Common Start Menu =>', winshell.start_menu (1)
print 'Programs =>', winshell.programs ()
print 'Common Programs =>', winshell.programs (1)
print 'Startup =>', winshell.startup ()
print 'Common Startup =>', winshell.startup (1)
print 'My Documents =>', winshell.my_documents ()
print 'Recent =>', winshell.recent ()
print 'SendTo =>', winshell.sendto ()

Structured Storage

In case you wondered, this is the stuff you get if you request File -> Properties from the Word 2000 menu (and presumably other versions as well). It's stored in a particular way which makes for easy indexing and so on.

import winshell
import os
for i in os.listdir ("."):
  if os.path.isfile (i):
    info = winshell.structured_storage (i)
    if info:
      print "%s => Title: %s Author: %s" % (i, info.get ("title", "Unknown"), info.get ("author", "Unknown"))

Thanks to Fernando Madruga for pointing out that a file with structured storage (eg an Excel file) can still raise an COM error (-2147287038) when you try to pull it out. This seems to happen if there are no user-added fields. I decided not to handle it internally to the module, but you can trap it yourself using the code below:

import pywintypes
import winshell
import os
for i in os.listdir ("."):
  if os.path.isfile (i):
    try:
      info = winshell.structured_storage (i)
    except pywintypes.com_error, (error_code, error_string, a, b):
      if error_code == -2147287038:
        print "%s: No user-defined info found" % i
      else:
        raise
    else:
      if info:
        print "%s => Title: %s Author: %s" % \
        (i, info.get ("title", "Unknown"), info.get ("author", "Unknown"))

Shell file copy/move/delete functions

The Windows shell provides an API to manipulate files in such a way that the operation can be undone by the user, and can be displayed with animated icons and where name clashes can be auto-renamed. This is what happens when you cut-and-paste in an Explorer window.

This functionality is all covered by one function call with a bunch of parameters and flags. To simplify things, this module provides four functions:

These each do what you expect, and use sensible defaults: ie allow for undo, resolve name clashes etc. So, for example, to delete a file into the recycle bin with an animated icon, so this:

import tempfile
import winshell

filename = tempfile.mktemp ()
open (filename, "w").close ()
winshell.delete_file (filename)
print filename, "sent to recycle bin"

... and now go and look in the Recycle Bin, and you should find the file you just deleted

Download

7th Mar 2006: winshell.py (v0.2, zipped - tiny) - readme - changelog

25th November 2003: winshell.py (v0.1, zipped - tiny)