I hit the wall with this. I need to create a python based COM server, pack it as exe windows and deploy it on windows. It must have a "full" interface - because the consumer requires an idispatch and a certain interface to work. Now I have created a com server and run it under the interpreter, and it works flawlessly with my picky client. However, when packing as an EXE - my local server - I get an error message in the log when the system tries to create it (even with a vbs script). So here it is. I searched high and low on itnernet and this seems like an import problem, but I don't know how to import my own python object for use by the local server.
This is python 2.7 with pywin32 extensions installed.
So first, the IDL I created for the server:
imtg.idl
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(4fafbb23-6a38-4613-b93b-68ea66c67043),
dual,
helpstring("IImtGroupApp Interface"),
pointer_default(unique)
]
interface IImtGroupApp : IDispatch
{
[id(1), helpstring("method EchoString")] HRESULT EchoString([in] BSTR in1, [out, retval] BSTR *vals);
[id(2), helpstring("method AddNumbers")] HRESULT AddNumbers([in] long in1, [in] long in2, [out, retval] long *vali);
};
[
uuid(d665e9d0-71a9-4e23-a1b4-abe3376d5c58),
version(1.0),
helpstring("ImtGroup 1.0 Type Library")
]
library IMTGROUPLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
importlib("msado15.dll");
[
uuid(ced66424-93fb-4307-9062-7bee76d3d8eb),
helpstring("ImtGroupApp Class")
]
coclass ImtGroupApp {
[default] interface IImtGroupApp;
};
};
Python - , , , .tlb - .idy - , .tbl , admin cmd.
imtg_server.py
import sys, os
import pythoncom
import win32com
import winerror
if hasattr(sys, 'frozen'):
print "is an exe"
pythoncom.frozen = 1
else:
print "not an exe"
class CImtg:
_reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER
_reg_clsid_ = "{24c0e3fe-58e7-4485-87dc-9f9e823b85e1}"
_reg_desc_ = "IMTGroup Python test object"
_reg_progid_ = "ImtGroup.Test"
if hasattr(sys, 'frozen'):
_reg_class_spec_ = "__main__.CImtg"
print "set reg_class_spec"
print _reg_class_spec_
_typelib_guid_ = '{d665e9d0-71a9-4e23-a1b4-abe3376d5c58}'
_typelib_version_ = 1, 0
_com_interfaces_ = ['IImtGroupApp']
def __init__(self):
self.MyProp1 = 10
def EchoString(self,in1):
return "Echoing " + in1
def AddNumbers(self, in1, in2):
return in1 + in2
def BuildTypelib():
from distutils.dep_util import newer
this_dir = os.path.dirname(__file__)
idl = os.path.abspath(os.path.join(this_dir, "imtg.idl"))
tlb=os.path.splitext(idl)[0] + '.tlb'
if os.path.isfile(idl):
if newer(idl, tlb):
print "Compiling %s" % (idl,)
rc = os.system ('midl "%s"' % (idl,))
if rc:
raise RuntimeError("Compiling MIDL failed!")
for fname in "dlldata.c imtg_i.c imtg_p.c imtg.h".split():
os.remove(os.path.join(this_dir, fname))
print "Registering %s" % (tlb,)
tli=pythoncom.LoadTypeLib(tlb)
pythoncom.RegisterTypeLib(tli,tlb)
def UnregisterTypelib():
k = CImtg
try:
pythoncom.UnRegisterTypeLib(k._typelib_guid_,
k._typelib_version_[0],
k._typelib_version_[1],
0,
pythoncom.SYS_WIN32)
print "Unregistered typelib"
except pythoncom.error, details:
if details[0]==winerror.TYPE_E_REGISTRYACCESS:
pass
else:
raise
if __name__=='__main__':
print "checking frozen"
if hasattr(sys, 'frozen'):
if '--unregister' in sys.argv or '--register' in sys.argv:
if '--unregister' in sys.argv:
UnregisterTypelib()
import win32com.server.register
win32com.server.register.UseCommandLine(CImtg)
else:
BuildTypelib()
import win32com.server.register
win32com.server.register.UseCommandLine(CImtg)
else:
import win32com.server
from win32com.server import localserver
print "starting the server"
localserver.main()
else:
if '--unregister' in sys.argv:
UnregisterTypelib()
import win32com.server.register
win32com.server.register.UseCommandLine(CImtg)
else:
if '--register' in sys.argv:
BuildTypelib()
import win32com.server.register
win32com.server.register.UseCommandLine(CImtg)
py2exe
, win32com.shell
setup_imtg.py
import modulefinder
import win32com, sys
for p in win32com.__path__[1:]:
modulefinder.AddPackagePath("win32com",p)
for extra in ["win32com.shell"]:
__import__(extra)
m = sys.modules[extra]
for p in m.__path__[1:]:
modulefinder.AddPackagePath(extra, p)
from distutils.core import setup
import py2exe
import sys
if len(sys.argv) == 1:
sys.argv.append("py2exe")
sys.argv.append("-q")
class Target:
def __init__(self, **kw):
self.__dict__.update(kw)
self.name = "IMTG Server"
CImtg = Target(
description = "Sample COM server",
modules = ["imtg_server"],
)
excludes = ["pywin", "pywin.debugger", "pywin.debugger.dbgcon",
"pywin.dialogs", "pywin.dialogs.list"]
options = {
"bundle_files": 1,
"compressed": 1,
"excludes": excludes,
"dll_excludes": ["w9xpopen.exe"]
}
setup(
options = {"py2exe": options},
zipfile = None,
com_server = [CImtg]
)
EXE
imtg_server --register
abou
-
vbs .
t.vbs
dim MD
set MD = CreateObject("ImtGroup.Test")
dim response
response = MD.EchoString("Really")
MsgBox(response)
.log, :
pythoncom error: ERROR: server.policy could not create an instance.
Traceback (most recent call last):
File "win32com\server\policy.pyc", line 136, in CreateInstance
File "win32com\server\policy.pyc", line 194, in _CreateInstance_
File "win32com\server\policy.pyc", line 727, in call_func
File "win32com\server\policy.pyc", line 717, in resolve_func
AttributeError: 'module' object has no attribute 'CImtg'
pythoncom error: Unexpected gateway error
Traceback (most recent call last):
File "win32com\server\policy.pyc", line 136, in CreateInstance
File "win32com\server\policy.pyc", line 194, in _CreateInstance_
File "win32com\server\policy.pyc", line 727, in call_func
File "win32com\server\policy.pyc", line 717, in resolve_func
AttributeError: 'module' object has no attribute 'CImtg'
pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)
, . , , . , , , :
_reg_class_spec_ = "__main__.CImtg"
. exe, , . , . , py2exe . imtg_server.CImtg, . CImtg, . win32com pythoncom - . "", , - - ? . .