Using Python to Create Shortcuts

At my job, I do a fair amount of system administration scripting in Python. For example, almost all the login scripts are written in Python (with some of them ported from Kixtart). Over the years, I’ve been tasked with creating shortcuts to new applications that need to be placed on the user’s desktop or in their Start Menu or both. In this article, I will show you how to accomplish this task.

Note: This is a Windows-only article, so if you don’t use that OS, then this will probably bore you to tears. Heck, it might do that anyway!

The first thing you’ll need to do much of anything on Windows is Mark Hammond’s PyWin32 package (AKA: Python for Windows extensions). I also recommend Tim Golden’s winshell module as it can make finding the user-specific folders much easier. I’ll be using Python 2.5 for this article, but as I understand it, PyWin32 is compatible with Python 3, so this tutorial could apply to those of you who use that too.

The simplest task I’ve had to do is to create a URL link on the user’s desktop. Unless you need to specify a specific browser, this is a really simple task:

import os, winshell
 
desktop = winshell.desktop()
path = os.path.join(desktop, "myNeatWebsite.url")
target = "http://www.google.com/"
 
shortcut = file(path, 'w')
shortcut.write('[InternetShortcut]\n')
shortcut.write('URL=%s' % target)
shortcut.close()

In the code above, we import the os and winshell modules. We use winshell to grab the current user’s desktop path and then use the os.path’s join() function to connect the path and the name of the url shortcut. Since this is Windows only, you really don’t need to do it this way. A string concatenation would work just as well. Note that we need to supply a “url” extension so Windows knows what to do. Then we write a file using the path we created before and write [InternetShortcut] as the first line. On the second line, we write the url target and then we close the file. That’s it!

The next example will be a little more complex. In it, we will use the win32com module from the PyWin32 package to create a shortcut to Media Player Classic, which is a nice open-source media player. Let’s take a look at some code so we can see how to do this thing:

import os, winshell
from win32com.client import Dispatch
 
desktop = winshell.desktop()
path = os.path.join(desktop, "Media Player Classic.lnk")
target = r"P:\Media\Media Player Classic\mplayerc.exe"
wDir = r"P:\Media\Media Player Classic"
icon = r"P:\Media\Media Player Classic\mplayerc.exe"
 
shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(path)
shortcut.Targetpath = target
shortcut.WorkingDirectory = wDir
shortcut.IconLocation = icon
shortcut.save()

The main takeaway here is the shell part. First you import Dispatch from win32com.client, then you call Dispatch(‘WScript.Shell’) to get a shell object (sort of) which you then use to create a shortcut object. Once you have that, you can assign values to the shortcut’s attributes, which are Targetpath, WorkingDirectory and IconLocation. Note that WorkingDirectory corresponds to the “Start In” field in a normal shortcut’s property dialog. In the script above, the IconLocation can be an icon file or it can extract the icon directly from the executable. One small got’cha here is that if you don’t call save, then the icon will not be created. In the previous example, we don’t explicitly have to call close on the file object because Python will take care of that for us when the script finishes.

Let’s take these two examples and make a reusable function out of them so we can use them in any login script we want:

from win32com.client import Dispatch
 
def createShortcut(path, target='', wDir='', icon=''):    
    ext = path[-3:]
    if ext == 'url':
        shortcut = file(path, 'w')
        shortcut.write('[InternetShortcut]\n')
        shortcut.write('URL=%s' % target)
        shortcut.close()
    else:
        shell = Dispatch('WScript.Shell')
        shortcut = shell.CreateShortCut(path)
        shortcut.Targetpath = target
        shortcut.WorkingDirectory = wDir
        if icon == '':
            pass
        else:
            shortcut.IconLocation = icon
        shortcut.save()

One obvious improvement we could add to this would be to use the os.path.dirname method to extract the Working Directory from the target and eliminate the need to pass that information in. Of course, I’ve seen some screwy shortcuts that don’t specify the target or the Working Directory at all! Anyway, I hope you will find this article helpful in your scripting. Until next time!

Print Friendly
  • Hi Mike, great article.

    Just a small comment: you say (first code explanation) and then use the os module’s path function to join the path and the name of the url shortcut

    Probably should be and then use the os.path module’s join() function

    Since this is Windows-only, you probably could just write (in the code) path = desktop + \myNeatWebsite.url

  • Hi Mike, great article.

    Just a small comment: you say (first code explanation) \and then use the os module’s path function to join the path and the name of the url shortcut\

    Probably should be \and then use the os.path module’s join() function\

    Since this is Windows-only, you probably could just write (in the code) path = desktop + \\myNeatWebsite.url\

  • @ Tim,

    Thanks for the links. I’m pretty sure those weren’t there when I originally came up with these methods as I Googled all over and visit your site quite a bit.

    @ Steven,

    I actually did think that line sounded weird when I wrote it. I’ve updated the text some to make it better and also added a note about concatenation as an alternative.

    Thanks for the feedback, you guys!

    – Mike

  • @ Tim,

    Thanks for the links. I’m pretty sure those weren’t there when I originally came up with these methods as I Googled all over and visit your site quite a bit.

    @ Steven,

    I actually did think that line sounded weird when I wrote it. I’ve updated the text some to make it better and also added a note about concatenation as an alternative.

    Thanks for the feedback, you guys!

    – Mike

  • @ Domen,

    I use Inno Setup to create an installer for my applications. It’s quite handy.

    – Mike

  • @ Domen,

    I use Inno Setup to create an installer for my applications. It’s quite handy.

    – Mike

  • Steve M.

    Hi Mike,
    Have you managed to make shortcuts work?
    I have failed in the past miserably and Since then I have stayed away “Inno the great”. How did you do? Any tutorial you used?

    Thanks

  • @ Steve,

    I just followed the directions on Inno’s website to get the links to work. Note that I created an executable using GUI2Exe first. You can check all that out in this tutorial I wrote:

    http://www.blog.pythonlibrary.org/2008/08/27/packaging-wxpymail-for-distribution/

    Hope that helps!

    – Mike

  • Very useful tutorial !

    I translated this article and Tim Golden’s to Spanish and published the all-in-one version in my blog

    http://simelo-es.blogspot.com/2010/03/tutorial-como-crear-enlaces-directos-en.html

    Hope this will be valuable for native Spanish speakers

  • Very useful tutorial !

    I translated this article and Tim Golden’s to Spanish and published the all-in-one version in my blog

    http://simelo-es.blogspot.com/2010/03/tutorial-como-crear-enlaces-directos-en.html

    Hope this will be valuable for native Spanish speakers

  • Anonymous

    I actually did think that line sounded weird when I wrote it. I’ve updated the text some to make it better and also added a note about concatenation as an alternative.

    Thanks for the feedback, you guys!new release air jordan