py2exe com dll问题
我正在尝试用 python 制作一个 com dll。但我尝试注册到编译的 dll 时出现错误消息“运行时错误 r6034”和“无法加载 python dll”这个问题的解决方案是什么?
mycode:
setup.py:
# This is the distutils script for creating a Python-based com dll
# server using ctypes.com. This script should be run like this:
#
# % python setup.py py2exe
#
# After you run this (from this directory) you will find two directories here:
# "build" and "dist". The .dll file in dist is what you are looking for.
##############################################################################
from distutils.core import setup
import py2exe
import sys
class Target:
def __init__(self, **kw):
self.__dict__.update(kw)
# for the version info resources (Properties -- Version)
self.version = "0.0.1"
self.company_name = "my company"
self.copyright = "2006, my company"
self.name = "my com server name"
my_com_server_target = Target(
description = "my com server",
# use module name for ctypes.com dll server
modules = ["view.view"],
# the following line embeds the typelib within the dll
#other_resources = [("TYPELIB", 1, open(r"view\view.tlb", "rb").read())],
# we only want the inproc (dll) server
create_exe = False
)
setup(
name="my_com_server",
# the following two parameters embed support files within dll file
options={"py2exe": {"bundle_files": 1, }},
zipfile=None,
version="0.0.1",
description="my com server",
# author, maintainer, contact go here:
author="First Last",
author_email="some_name@some_company.com",
packages=["view"],
ctypes_com_server=[my_com_server_target]
)
和view.py:
# -*- coding: utf-8 -*-
# A sample context menu handler.
# Adds a 'Hello from Python' menu entry to .py files. When clicked, a
# simple message box is displayed.
#
# To demostrate:
# * Execute this script to register the context menu.
# * Open Windows Explorer, and browse to a directory with a .py file.
# * Right-Click on a .py file - locate and click on 'Hello from Python' on
# the context menu.
import ConfigParser
import os.path
import urllib
import pythoncom
from win32com.shell import shell, shellcon
import win32gui
import win32con
IContextMenu_Methods = ["QueryContextMenu", "InvokeCommand", "GetCommandString"]
IShellExtInit_Methods = ["Initialize"]
#HKCR Key Affected object types
#* All files
#AllFileSystemObjects All regular files and file folders
#Folder All folders, virtual and filesystem
#Directory File folders
#Drive Root folders of all system drives
#Network Entire network
#NetShare All network shares
TYPES = [
'*',
'Directory',
]
SUBKEY = 'MindRetrieve'
def alertError(hwnd, exc):
win32gui.MessageBox(hwnd, str(exc), str(exc.__class__), win32con.MB_OK)
class ShellExtension:
_reg_progid_ = "MindRetrieve.ShellExtension.ContextMenu"
_reg_desc_ = "MindRetrieve Shell Extension (context menu)"
_reg_clsid_ = "{ABB05546-EB55-4433-B068-A57667706828}"
_com_interfaces_ = [shell.IID_IShellExtInit, shell.IID_IContextMenu]
_public_methods_ = IContextMenu_Methods + IShellExtInit_Methods
def Initialize(self, folder, dataobj, hkey):
print "Init", folder, dataobj, hkey
self.dataobj = dataobj
def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags):
print "QCM", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags
try:
# Query the items clicked on
# files = self.getFiles()
# msg = len(files) > 1 and '&Tag %s files' % len(files) or '&Tag with MindRetrieve'
# # TODO: we do not support tagging multiple files now
# if not(files):
# return
msg = '&Tag with MindRetrieve'
idCmd = idCmdFirst
items = []
if (uFlags & 0x000F) == shellcon.CMF_NORMAL: # Check == here, since CMF_NORMAL=0
print "CMF_NORMAL..."
items.append(msg)
elif uFlags & shellcon.CMF_VERBSONLY:
print "CMF_VERBSONLY..."
items.append(msg)# + " - shortcut")
elif uFlags & shellcon.CMF_EXPLORE:
print "CMF_EXPLORE..."
items.append(msg)# + " - normal file, right-click in Explorer")
elif uFlags & shellcon.CMF_DEFAULTONLY:
print "CMF_DEFAULTONLY...\r\n"
else:
print "** unknown flags", uFlags
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
0, None)
indexMenu += 1
for item in items:
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_STRING|win32con.MF_BYPOSITION,
idCmd, item)
indexMenu += 1
idCmd += 1
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
0, None)
indexMenu += 1
return idCmd-idCmdFirst # Must return number of menu items we added.
except Exception, e:
alertError(hwnd, e)
raise
def InvokeCommand(self, ci):
mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci
try:
files = self.getFiles()
if not files:
return
fname = files[0]
# win32gui.MessageBox(hwnd, fname, str(fname.__class__), win32con.MB_OK)
fname = fname.encode('utf-8')
file_url = urllib.pathname2url(fname)
# 2005-12-20 Test urllib.pathname2url()
#
#>>> urllib.pathname2url(r'c:\tung\wäi')
#'///C|/tung/w%84i'
#>>> urllib.pathname2url(r'\tung\wäi')
#'/tung/w%84i'
#>>> urllib.pathname2url(r'tung\wäi')
#'tung/w%84i'
# prefer ':' as the drive separator rather than '|'
if file_url.startswith('///') and file_url[4:5] == '|':
file_url = file_url.replace('|',':',1)
if file_url.startswith('//'):
file_url = 'file:' + file_url
elif file_url.startswith('/'):
file_url = 'file://' + file_url
else:
# fname is a relative filename? Should not happen!
file_url = 'file:///' + file_url
url = getBaseURL() + '?url=' + urllib.quote(file_url)
shell.ShellExecuteEx(fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpFile=url,
nShow=win32con.SW_NORMAL,
)
except Exception, e:
alertError(hwnd, e)
raise
def GetCommandString(self, cmd, typ):
return "&Tag with MindRetrieve"
def getFiles(self):
format_etc = win32con.CF_HDROP, None, 1, -1, pythoncom.TYMED_HGLOBAL
sm = self.dataobj.GetData(format_etc)
num_files = shell.DragQueryFile(sm.data_handle, -1)
files = [shell.DragQueryFile(sm.data_handle, i) for i in range(num_files)]
return files
def getConfigPath():
""" get the DLL path from registry """
import _winreg
# _winreg.QueryValue() may throw WindowsError
# COM server registration in deployed environment
# e.g. HKEY_CLASSES_ROOT\CLSID\{ABB05546-EB55-4433-B068-A57667706828}\InprocServer32
# =c:\Program Files\MindRetrieve\context_menu.dll
subkey = 'CLSID\\%s\\InprocServer32' % ShellExtension._reg_clsid_
path = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, subkey)
head, tail = os.path.split(path)
# quick check if this is in deployed environment
if os.path.isabs(head):
return head
# Otherwise assume in development environment
# e.g. HKEY_CLASSES_ROOT\CLSID\{ABB05546-EB55-4433-B068-A57667706828}\PythonCOMPath
# =g:\bin\py_repos\mindretrieve\trunk\minds\weblib\win32
subkey = 'CLSID\\%s\\PythonCOMPath' % ShellExtension._reg_clsid_
path = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, subkey)
idx = path.lower().rfind('minds') # truncate trailing 'minds\weblib\win32'
if idx > 0:
path = path[:idx-1]
return path
def getHTTPAdminPort():
""" get HTTP.admin_port from config.ini """
pathname = os.path.join(getConfigPath(), 'config.ini')
cp = ConfigParser.ConfigParser()
cp.read(pathname)
admin_port = cp.getint('http','admin_port')
return admin_port
def getBaseURL():
""" get the base URL """
port = getHTTPAdminPort()
return 'http://localhost:%s/weblib/_' % port
def DllRegisterServer():
import _winreg
for typ in TYPES:
# e.g. HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\MindRetrieve
key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, "%s\\shellex" % typ)
subkey = _winreg.CreateKey(key, "ContextMenuHandlers")
subkey2 = _winreg.CreateKey(subkey, SUBKEY)
_winreg.SetValueEx(subkey2, None, 0, _winreg.REG_SZ, ShellExtension._reg_clsid_)
print ShellExtension._reg_desc_, "registration complete."
def DllUnregisterServer():
import _winreg
for typ in TYPES:
try:
# e.g. HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\MindRetrieve
key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, "%s\\shellex\\ContextMenuHandlers\\%s" % (typ, SUBKEY))
except WindowsError, details:
import errno
if details.errno != errno.ENOENT:
raise
print ShellExtension._reg_desc_, "unregistration complete."
def main(argv):
# assume argv == sys.argv
from win32com.server import register
register.UseCommandLine(ShellExtension,
finalize_register = DllRegisterServer,
finalize_unregister = DllUnregisterServer)
def test(argv):
""" adhoc tests """
print 'URL:', getBaseURL()
if __name__=='__main__':
import sys
if '-t' not in sys.argv:
main(sys.argv)
else:
test(sys.argv)
i'm trying making a com dll in python. but i try register to compiled dll have a error message "run time error r6034" and "could not load python dll" what is the solution this problem ?
mycode :
setup.py:
# This is the distutils script for creating a Python-based com dll
# server using ctypes.com. This script should be run like this:
#
# % python setup.py py2exe
#
# After you run this (from this directory) you will find two directories here:
# "build" and "dist". The .dll file in dist is what you are looking for.
##############################################################################
from distutils.core import setup
import py2exe
import sys
class Target:
def __init__(self, **kw):
self.__dict__.update(kw)
# for the version info resources (Properties -- Version)
self.version = "0.0.1"
self.company_name = "my company"
self.copyright = "2006, my company"
self.name = "my com server name"
my_com_server_target = Target(
description = "my com server",
# use module name for ctypes.com dll server
modules = ["view.view"],
# the following line embeds the typelib within the dll
#other_resources = [("TYPELIB", 1, open(r"view\view.tlb", "rb").read())],
# we only want the inproc (dll) server
create_exe = False
)
setup(
name="my_com_server",
# the following two parameters embed support files within dll file
options={"py2exe": {"bundle_files": 1, }},
zipfile=None,
version="0.0.1",
description="my com server",
# author, maintainer, contact go here:
author="First Last",
author_email="some_name@some_company.com",
packages=["view"],
ctypes_com_server=[my_com_server_target]
)
and view.py:
# -*- coding: utf-8 -*-
# A sample context menu handler.
# Adds a 'Hello from Python' menu entry to .py files. When clicked, a
# simple message box is displayed.
#
# To demostrate:
# * Execute this script to register the context menu.
# * Open Windows Explorer, and browse to a directory with a .py file.
# * Right-Click on a .py file - locate and click on 'Hello from Python' on
# the context menu.
import ConfigParser
import os.path
import urllib
import pythoncom
from win32com.shell import shell, shellcon
import win32gui
import win32con
IContextMenu_Methods = ["QueryContextMenu", "InvokeCommand", "GetCommandString"]
IShellExtInit_Methods = ["Initialize"]
#HKCR Key Affected object types
#* All files
#AllFileSystemObjects All regular files and file folders
#Folder All folders, virtual and filesystem
#Directory File folders
#Drive Root folders of all system drives
#Network Entire network
#NetShare All network shares
TYPES = [
'*',
'Directory',
]
SUBKEY = 'MindRetrieve'
def alertError(hwnd, exc):
win32gui.MessageBox(hwnd, str(exc), str(exc.__class__), win32con.MB_OK)
class ShellExtension:
_reg_progid_ = "MindRetrieve.ShellExtension.ContextMenu"
_reg_desc_ = "MindRetrieve Shell Extension (context menu)"
_reg_clsid_ = "{ABB05546-EB55-4433-B068-A57667706828}"
_com_interfaces_ = [shell.IID_IShellExtInit, shell.IID_IContextMenu]
_public_methods_ = IContextMenu_Methods + IShellExtInit_Methods
def Initialize(self, folder, dataobj, hkey):
print "Init", folder, dataobj, hkey
self.dataobj = dataobj
def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags):
print "QCM", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags
try:
# Query the items clicked on
# files = self.getFiles()
# msg = len(files) > 1 and '&Tag %s files' % len(files) or '&Tag with MindRetrieve'
# # TODO: we do not support tagging multiple files now
# if not(files):
# return
msg = '&Tag with MindRetrieve'
idCmd = idCmdFirst
items = []
if (uFlags & 0x000F) == shellcon.CMF_NORMAL: # Check == here, since CMF_NORMAL=0
print "CMF_NORMAL..."
items.append(msg)
elif uFlags & shellcon.CMF_VERBSONLY:
print "CMF_VERBSONLY..."
items.append(msg)# + " - shortcut")
elif uFlags & shellcon.CMF_EXPLORE:
print "CMF_EXPLORE..."
items.append(msg)# + " - normal file, right-click in Explorer")
elif uFlags & shellcon.CMF_DEFAULTONLY:
print "CMF_DEFAULTONLY...\r\n"
else:
print "** unknown flags", uFlags
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
0, None)
indexMenu += 1
for item in items:
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_STRING|win32con.MF_BYPOSITION,
idCmd, item)
indexMenu += 1
idCmd += 1
win32gui.InsertMenu(hMenu, indexMenu,
win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
0, None)
indexMenu += 1
return idCmd-idCmdFirst # Must return number of menu items we added.
except Exception, e:
alertError(hwnd, e)
raise
def InvokeCommand(self, ci):
mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci
try:
files = self.getFiles()
if not files:
return
fname = files[0]
# win32gui.MessageBox(hwnd, fname, str(fname.__class__), win32con.MB_OK)
fname = fname.encode('utf-8')
file_url = urllib.pathname2url(fname)
# 2005-12-20 Test urllib.pathname2url()
#
#>>> urllib.pathname2url(r'c:\tung\wäi')
#'///C|/tung/w%84i'
#>>> urllib.pathname2url(r'\tung\wäi')
#'/tung/w%84i'
#>>> urllib.pathname2url(r'tung\wäi')
#'tung/w%84i'
# prefer ':' as the drive separator rather than '|'
if file_url.startswith('///') and file_url[4:5] == '|':
file_url = file_url.replace('|',':',1)
if file_url.startswith('//'):
file_url = 'file:' + file_url
elif file_url.startswith('/'):
file_url = 'file://' + file_url
else:
# fname is a relative filename? Should not happen!
file_url = 'file:///' + file_url
url = getBaseURL() + '?url=' + urllib.quote(file_url)
shell.ShellExecuteEx(fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpFile=url,
nShow=win32con.SW_NORMAL,
)
except Exception, e:
alertError(hwnd, e)
raise
def GetCommandString(self, cmd, typ):
return "&Tag with MindRetrieve"
def getFiles(self):
format_etc = win32con.CF_HDROP, None, 1, -1, pythoncom.TYMED_HGLOBAL
sm = self.dataobj.GetData(format_etc)
num_files = shell.DragQueryFile(sm.data_handle, -1)
files = [shell.DragQueryFile(sm.data_handle, i) for i in range(num_files)]
return files
def getConfigPath():
""" get the DLL path from registry """
import _winreg
# _winreg.QueryValue() may throw WindowsError
# COM server registration in deployed environment
# e.g. HKEY_CLASSES_ROOT\CLSID\{ABB05546-EB55-4433-B068-A57667706828}\InprocServer32
# =c:\Program Files\MindRetrieve\context_menu.dll
subkey = 'CLSID\\%s\\InprocServer32' % ShellExtension._reg_clsid_
path = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, subkey)
head, tail = os.path.split(path)
# quick check if this is in deployed environment
if os.path.isabs(head):
return head
# Otherwise assume in development environment
# e.g. HKEY_CLASSES_ROOT\CLSID\{ABB05546-EB55-4433-B068-A57667706828}\PythonCOMPath
# =g:\bin\py_repos\mindretrieve\trunk\minds\weblib\win32
subkey = 'CLSID\\%s\\PythonCOMPath' % ShellExtension._reg_clsid_
path = _winreg.QueryValue(_winreg.HKEY_CLASSES_ROOT, subkey)
idx = path.lower().rfind('minds') # truncate trailing 'minds\weblib\win32'
if idx > 0:
path = path[:idx-1]
return path
def getHTTPAdminPort():
""" get HTTP.admin_port from config.ini """
pathname = os.path.join(getConfigPath(), 'config.ini')
cp = ConfigParser.ConfigParser()
cp.read(pathname)
admin_port = cp.getint('http','admin_port')
return admin_port
def getBaseURL():
""" get the base URL """
port = getHTTPAdminPort()
return 'http://localhost:%s/weblib/_' % port
def DllRegisterServer():
import _winreg
for typ in TYPES:
# e.g. HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\MindRetrieve
key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, "%s\\shellex" % typ)
subkey = _winreg.CreateKey(key, "ContextMenuHandlers")
subkey2 = _winreg.CreateKey(subkey, SUBKEY)
_winreg.SetValueEx(subkey2, None, 0, _winreg.REG_SZ, ShellExtension._reg_clsid_)
print ShellExtension._reg_desc_, "registration complete."
def DllUnregisterServer():
import _winreg
for typ in TYPES:
try:
# e.g. HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\MindRetrieve
key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, "%s\\shellex\\ContextMenuHandlers\\%s" % (typ, SUBKEY))
except WindowsError, details:
import errno
if details.errno != errno.ENOENT:
raise
print ShellExtension._reg_desc_, "unregistration complete."
def main(argv):
# assume argv == sys.argv
from win32com.server import register
register.UseCommandLine(ShellExtension,
finalize_register = DllRegisterServer,
finalize_unregister = DllUnregisterServer)
def test(argv):
""" adhoc tests """
print 'URL:', getBaseURL()
if __name__=='__main__':
import sys
if '-t' not in sys.argv:
main(sys.argv)
else:
test(sys.argv)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
根据有关错误 R6034 的文档,这意味着您加载 C 运行时库是错误的,因为您缺少“清单”。根据此线程,看来所需的方法只是:
(无法验证这是真的,因为我仍然没有可用的 Windows - 我现在拥有一台便宜的翻新 Windows 机器,得到它只是为了尝试帮助更多人解决此类问题,但找不到防病毒磁盘如果没有的话,我当然无法安全地上网)。
py2exe 的教程 涵盖了捆绑运行时库并为其制作清单的问题,并且比上面引用的简短解释更详细。
Per the docs about error R6034, it means you're loading the C runtime libraries wrong because you're missing a "manifest". Per this thread, it seems the needed approach is just:
(can't verify that this is true as I still have no working Windows -- I now do own a cheap refurb Windows machine, got it just to try and help more with such problems, but can't find the antivirus disk and without one of course I can't safely go online).
py2exe's tutorial covers the issues of bundling the runtime libraries and making a manifest for that, and goes in more details than the above-quoted short explanation.
我看到一个潜在的问题。您将
view
指定为包名称和模块名称。这很令人困惑,也不推荐。至少为了获得帮助,请将包重命名为view_p
(或更具描述性的名称),以便我们可以引用其中一个。现在:
并且
view.py
进入名为view_p
的目录,并且在该目录中,还应该有一个__init__.py
。One potential problem I see. You're specifying
view
as both a package name and a module name. This is confusing as well as not recommended. At least for the purposes of getting help, rename the package toview_p
(or something more descriptive) so we can reference one or another.So now:
and
And
view.py
goes in a directory calledview_p
and in that directory, there should also be a__init__.py
.我看到的另一个潜在问题是您正在使用 pywin32 构建 COM 服务器,但您正在使用 py2exe 的“ctypes_com_server”参数。也许这是受支持的,但这些实现之间可能存在一些不兼容性,从而妨碍您的预期使用。
Another potential problem I see is you're using pywin32 to construct your COM server but you're using the "ctypes_com_server" parameter to py2exe. Maybe this is supported, but it's possible that there are some incompatibility across these implementations that prevents your intended usage.