I am trying to use the create_shortcut() function in a post-installation script in Python 3.2, per http://docs.python.org/distutils/builtdist.html#the-postinstallation-script . Every time I try to run the function, i get the following:
NameError: name 'create_shortcut' is not defined
I feel like I am missing an import, but I can't seem to find any documentation anywhere on how to get this working.
EDIT I should have specified earlier my final goal and my environment. I am building an .msi running the following: python setup.py bdist_msi --initial-target-dir="C:\path\to\install" --install-script="install.py" The install.py file lives in the same directory as my setup.py.
The final goal is to have a .msi file that installs the application in the specified directory and creates a Start Menu item in a specified location. It would be a nice to have if the installer allows the user to select to create the Start Menu shortcut or a desktop shortcut.
Postinstallation script is to run in the native Windows installation routine.
Fuctions get_special_folder_path
, directory_created
, directory_created
and create_shortcut
are not pythonic: for example, they cannot be called as keyword-argument pairs - only positionally. The functions are defined at https://github.com/python/cpython/blob/master/PC/bdist_wininst/install.c
A routine for the shorcut creation acts as a wrapper around system interface IShellLink
( "lives" in shell32.dll ) and starts at line 504:
static PyObject *CreateShortcut(PyObject *self, PyObject *args)
{...
and then is linked at line 643:
PyMethodDef meth[] = {
{"create_shortcut", CreateShortcut, METH_VARARGS, NULL},
{"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL},
...
};
In your local installation the above C code is already compiled in the executables:
C:\Python26\Lib\distutils\command\wininst-6.0.exe
C:\Python26\Lib\distutils\command\wininst-7.1.exe
C:\Python26\Lib\distutils\command\wininst-8.0.exe
C:\Python26\Lib\distutils\command\wininst-9.0.exe
C:\Python26\Lib\distutils\command\wininst-9.0-amd64.exe
So, answer: There is no python lib to import the function create_shortcut(), it is available as-is only inside a Windows postinstallation script.
If you want to support both automatic and manual postinstall scenarios, look at the pywin32 workaround:
https://github.com/mhammond/pywin32/blob/master/pywin32_postinstall.py line 80
try:
create_shortcut
except NameError:
# Create a function with the same signature as create_shortcut provided
# by bdist_wininst
def create_shortcut(path, description, filename,
arguments="", workdir="", iconpath="", iconindex=0):
import pythoncom
from win32com.shell import shell, shellcon
ilink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None,
pythoncom.CLSCTX_INPROC_SERVER,
shell.IID_IShellLink)
ilink.SetPath(path)
ilink.SetDescription(description)
if arguments:
ilink.SetArguments(arguments)
if workdir:
ilink.SetWorkingDirectory(workdir)
if iconpath or iconindex:
ilink.SetIconLocation(iconpath, iconindex)
# now save it.
ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile)
ipf.Save(filename, 0)
As the documentation says:
Starting with Python 2.3, a postinstallation script can be specified with the --install-script option. The basename of the script must be specified, and the script filename must also be listed in the scripts argument to the setup function.
These are windows only options, you need to use it when you build a executable installer of your module. Try:
python setup.py bdist_wininst --help
python setup.py bdist_wininst --install-script postinst.py --pre-install-script preinst.py
This file needs to go in the "script" section of your setup.py file.
Some functions especially useful in this context are available as additional built-in functions in the installation script.
This means you don't have to import any module.