我正在尝试在 Python 3.2 的安装后脚本中使用 create_shortcut() 函数,根据 http://docs.python.org/distutils/builtdist.html#the-postinstallation-script .每次我尝试运行该函数时,我都会得到以下信息:
NameError: name 'create_shortcut' is not defined
我觉得我缺少一个导入,但我似乎无法在任何地方找到任何关于如何让它工作的文档。
编辑 我应该早点指定我的最终目标和我的环境。我正在构建一个运行以下命令的 .msi: python setup.py bdist_msi --initial-target-dir="C:\path\to\install"--install-script="install.py" install.py 文件与我的 setup.py 位于同一目录中。
最终目标是拥有一个 .msi 文件,在指定目录中安装应用程序并在指定位置创建开始菜单项。如果安装程序允许用户选择创建开始菜单快捷方式或桌面快捷方式,那就太好了。
请您参考如下方法:
安装后脚本将在 native Windows 安装例程中运行。
函数 get_special_folder_path、directory_created、directory_created 和 create_shortcut 不是 pythonic:例如,它们不能被调用作为关键字参数对 - 仅在位置上。这些函数在 https://github.com/python/cpython/blob/master/PC/bdist_wininst/install.c 中定义
创建快捷方式的例程充当系统接口(interface)的包装器 IShellLink (“存在于”shell32.dll 中)并从第 504 行开始:
static PyObject *CreateShortcut(PyObject *self, PyObject *args)
{...
然后在第 643 行链接:
PyMethodDef meth[] = {
{"create_shortcut", CreateShortcut, METH_VARARGS, NULL},
{"get_special_folder_path", GetSpecialFolderPath, METH_VARARGS, NULL},
...
};
在您的本地安装中,上面的 C 代码已经编译到可执行文件中:
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
所以,回答:没有导入函数 create_shortcut() 的 python 库,它仅在 Windows 安装后脚本中按原样可用。
如果您想同时支持自动和手动安装后方案,请查看 pywin32 解决方法:
https://github.com/mhammond/pywin32/blob/master/pywin32_postinstall.py第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)
