def check_is_admin():
global _is_admin
if _is_admin is None:
from win32com.shell.shell import IsUserAnAdmin
import pythoncom
try:
_is_admin = IsUserAnAdmin()
except pythoncom.com_error, exc:
if exc.hresult != winerror.E_NOTIMPL:
raise
# not impl on this platform - must be old - assume is admin
_is_admin = True
return _is_admin
# If this exception is raised by a test, the test is reported as a 'skip'
python类com_error()的实例源码
def GetModuleForProgID(progid):
"""Get a Python module for a Program ID
Given a Program ID, return a Python module which contains the
class which wraps the COM object.
Returns the Python module, or None if no module is available.
Params
progid -- A COM ProgramID or IID (eg, "Word.Application")
"""
try:
iid = pywintypes.IID(progid)
except pywintypes.com_error:
return None
return GetModuleForCLSID(iid)
def MakeModuleForTypelibInterface(typelib_ob, progressInstance = None, bForDemand = bForDemandDefault, bBuildHidden = 1):
"""Generate support for a type library.
Given a PyITypeLib interface generate and import the necessary support files. This is useful
for getting makepy support for a typelibrary that is not registered - the caller can locate
and load the type library itself, rather than relying on COM to find it.
Returns the Python module.
Params
typelib_ob -- The type library itself
progressInstance -- Instance to use as progress indicator, or None to
use the GUI progress bar.
"""
import makepy
try:
makepy.GenerateFromTypeLibSpec( typelib_ob, progressInstance=progressInstance, bForDemand = bForDemandDefault, bBuildHidden = bBuildHidden)
except pywintypes.com_error:
return None
tla = typelib_ob.GetLibAttr()
guid = tla[0]
lcid = tla[1]
major = tla[3]
minor = tla[4]
return GetModuleForTypelib(guid, lcid, major, minor)
def EnsureDispatch(prog_id, bForDemand = 1): # New fn, so we default the new demand feature to on!
"""Given a COM prog_id, return an object that is using makepy support, building if necessary"""
disp = win32com.client.Dispatch(prog_id)
if not disp.__dict__.get("CLSID"): # Eeek - no makepy support - try and build it.
try:
ti = disp._oleobj_.GetTypeInfo()
disp_clsid = ti.GetTypeAttr()[0]
tlb, index = ti.GetContainingTypeLib()
tla = tlb.GetLibAttr()
mod = EnsureModule(tla[0], tla[1], tla[3], tla[4], bForDemand=bForDemand)
GetModuleForCLSID(disp_clsid)
# Get the class from the module.
import CLSIDToClass
disp_class = CLSIDToClass.GetClass(str(disp_clsid))
disp = disp_class(disp._oleobj_)
except pythoncom.com_error:
raise TypeError("This COM object can not automate the makepy process - please run makepy manually for this object")
return disp
def WriteClassHeader(self, generator):
generator.checkWriteDispatchBaseClass()
doc = self.doc
stream = generator.file
print >> stream, 'class ' + self.python_name + '(DispatchBaseClass):'
if doc[1]: print >> stream, '\t' + build._makeDocString(doc[1])
try:
progId = pythoncom.ProgIDFromCLSID(self.clsid)
print >> stream, "\t# This class is creatable by the name '%s'" % (progId)
except pythoncom.com_error:
pass
print >> stream, "\tCLSID = " + repr(self.clsid)
if self.coclass_clsid is None:
print >> stream, "\tcoclass_clsid = None"
else:
print >> stream, "\tcoclass_clsid = " + repr(self.coclass_clsid)
print >> stream
self.bWritten = 1
def _Build_CoClass(self, type_info_tuple):
info, infotype, doc, attr = type_info_tuple
# find the source and dispinterfaces for the coclass
child_infos = []
for j in range(attr[8]):
flags = info.GetImplTypeFlags(j)
try:
refType = info.GetRefTypeInfo(info.GetRefTypeOfImplType(j))
except pythoncom.com_error:
# Can't load a dependent typelib?
continue
refAttr = refType.GetTypeAttr()
child_infos.append( (info, refAttr.typekind, refType, refType.GetDocumentation(-1), refAttr, flags) )
# Done generating children - now the CoClass itself.
newItem = CoClassItem(info, attr, doc)
return newItem, child_infos
def __init__(self, oobj=None):
if oobj is None:
oobj = pythoncom.new(self.CLSID)
elif isinstance(oobj, DispatchBaseClass):
try:
oobj = oobj._oleobj_.QueryInterface(self.CLSID, pythoncom.IID_IDispatch) # Must be a valid COM instance
except pythoncom.com_error, details:
import winerror
# Some stupid objects fail here, even tho it is _already_ IDispatch!!??
# Eg, Lotus notes.
# So just let it use the existing object if E_NOINTERFACE
if details.hresult != winerror.E_NOINTERFACE:
raise
oobj = oobj._oleobj_
self.__dict__["_oleobj_"] = oobj # so we dont call __setattr__
# Provide a prettier name than the CLSID
def test():
import win32com.client
oldcwd = os.getcwd()
try:
session = gencache.EnsureDispatch("MAPI.Session")
try:
session.Logon(GetDefaultProfileName())
except pythoncom.com_error, details:
print "Could not log on to MAPI:", details
return
except pythoncom.error:
# no mapi.session - let's try outlook
app = gencache.EnsureDispatch("Outlook.Application")
session = app.Session
try:
TestUser(session)
TestAddress(session)
DumpFolders(session)
finally:
session.Logoff()
# It appears Exchange will change the cwd on us :(
os.chdir(oldcwd)
def TestDynamic():
progress("Testing Dynamic")
import win32com.client.dynamic
o = win32com.client.dynamic.DumbDispatch("PyCOMTest.PyCOMTest")
TestCommon(o, False)
counter = win32com.client.dynamic.DumbDispatch("PyCOMTest.SimpleCounter")
TestCounter(counter, False)
# Dynamic doesn't know this should be an int, so we get a COM
# TypeMismatch error.
try:
check_get_set_raises(ValueError, o.GetSetInt, "foo")
raise error("no exception raised")
except pythoncom.com_error, exc:
if exc.hresult != winerror.DISP_E_TYPEMISMATCH:
raise
# damn - props with params don't work for dynamic objects :(
# o.SetParamProp(0, 1)
# if o.ParamProp(0) != 1:
# raise RuntimeError, o.paramProp(0)
def DispExTest(ob):
if not __debug__: print "WARNING: Tests dressed up as assertions are being skipped!"
assert ob.GetDispID("Add", 0)==10, "Policy did not honour the dispid"
# Not impl
# assert ob.GetMemberName(10, 0)=="add", "Policy did not give me the correct function for the dispid"
assert ob.GetDispID("Remove", 0)==11, "Policy did not honour the dispid"
assert ob.GetDispID("In", 0)==1000, "Allocated dispid unexpected value"
assert ob.GetDispID("_NewEnum", 0)==pythoncom.DISPID_NEWENUM, "_NewEnum() got unexpected DISPID"
dispids = []
dispid = -1
while 1:
try:
dispid = ob.GetNextDispID(0, dispid)
dispids.append(dispid)
except pythoncom.com_error, (hr, desc, exc, arg):
assert hr==winerror.S_FALSE, "Bad result at end of enum"
break
dispids.sort()
if dispids != [pythoncom.DISPID_EVALUATE, pythoncom.DISPID_NEWENUM, 10, 11, 1000]:
raise Error("Got back the wrong dispids: %s" % dispids)
def testit(self):
ctx = pythoncom.CreateBindCtx()
rot = pythoncom.GetRunningObjectTable()
num = 0
for mk in rot:
name = mk.GetDisplayName(ctx, None)
num += 1
# Monikers themselves can iterate their contents (sometimes :)
try:
for sub in mk:
num += 1
except pythoncom.com_error, exc:
if exc.hresult != winerror.E_NOTIMPL:
raise
#if num < 2:
# print "Only", num, "objects in the ROT - this is unusual"
def testShellLink(self):
desktop = str(shell.SHGetSpecialFolderPath(0, CSIDL_DESKTOP))
num = 0
shellLink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
persistFile = shellLink.QueryInterface(pythoncom.IID_IPersistFile)
names = [os.path.join(desktop, n) for n in os.listdir(desktop)]
programs = str(shell.SHGetSpecialFolderPath(0, CSIDL_PROGRAMS))
names.extend([os.path.join(programs, n) for n in os.listdir(programs)])
for name in names:
try:
persistFile.Load(name,STGM_READ)
except pythoncom.com_error:
continue
# Resolve is slow - avoid it for our tests.
#shellLink.Resolve(0, shell.SLR_ANY_MATCH | shell.SLR_NO_UI)
fname, findData = shellLink.GetPath(0)
unc = shellLink.GetPath(shell.SLGP_UNCPRIORITY)[0]
num += 1
if num == 0:
# This isn't a fatal error, but is unlikely.
print "Could not find any links on your desktop or programs dir, which is unusual"
def _WaitForFinish(ob, timeout):
end = time.time() + timeout
while 1:
if msvcrt.kbhit():
msvcrt.getch()
break
pythoncom.PumpWaitingMessages()
stopEvent.wait(.2)
if stopEvent.isSet():
stopEvent.clear()
break
try:
if not ob.Visible:
# Gone invisible - we need to pretend we timed
# out, so the app is quit.
return 0
except pythoncom.com_error:
# Excel is busy (eg, editing the cell) - ignore
pass
if time.time() > end:
return 0
return 1
def OnConnection(self, application, connectMode, addin, custom):
print "OnConnection", application, connectMode, addin, custom
try:
self.appHostApp = application
cbcMyBar = self.appHostApp.CommandBars.Add(Name="PythonBar", Position=constants.msoBarTop, MenuBar=constants.msoBarTypeNormal, Temporary=True)
btnMyButton = cbcMyBar.Controls.Add(Type=constants.msoControlButton, Parameter="Greetings")
btnMyButton=self.toolbarButton = DispatchWithEvents(btnMyButton, ButtonEvent)
btnMyButton.Style = constants.msoButtonCaption
btnMyButton.BeginGroup = True
btnMyButton.Caption = "&Python"
btnMyButton.TooltipText = "Python rules the World"
btnMyButton.Width = "34"
cbcMyBar.Visible = True
except pythoncom.com_error, (hr, msg, exc, arg):
print "The Excel call failed with code %d: %s" % (hr, msg)
if exc is None:
print "There is no extended error information"
else:
wcode, source, text, helpFile, helpId, scode = exc
print "The source of the error is", source
print "The error message is", text
print "More info can be found in %s (id=%d)" % (helpFile, helpId)
def GetModuleForProgID(progid):
"""Get a Python module for a Program ID
Given a Program ID, return a Python module which contains the
class which wraps the COM object.
Returns the Python module, or None if no module is available.
Params
progid -- A COM ProgramID or IID (eg, "Word.Application")
"""
try:
iid = pywintypes.IID(progid)
except pywintypes.com_error:
return None
return GetModuleForCLSID(iid)
def MakeModuleForTypelibInterface(typelib_ob, progressInstance = None, bForDemand = bForDemandDefault, bBuildHidden = 1):
"""Generate support for a type library.
Given a PyITypeLib interface generate and import the necessary support files. This is useful
for getting makepy support for a typelibrary that is not registered - the caller can locate
and load the type library itself, rather than relying on COM to find it.
Returns the Python module.
Params
typelib_ob -- The type library itself
progressInstance -- Instance to use as progress indicator, or None to
use the GUI progress bar.
"""
import makepy
try:
makepy.GenerateFromTypeLibSpec( typelib_ob, progressInstance=progressInstance, bForDemand = bForDemandDefault, bBuildHidden = bBuildHidden)
except pywintypes.com_error:
return None
tla = typelib_ob.GetLibAttr()
guid = tla[0]
lcid = tla[1]
major = tla[3]
minor = tla[4]
return GetModuleForTypelib(guid, lcid, major, minor)
def EnsureDispatch(prog_id, bForDemand = 1): # New fn, so we default the new demand feature to on!
"""Given a COM prog_id, return an object that is using makepy support, building if necessary"""
disp = win32com.client.Dispatch(prog_id)
if not disp.__dict__.get("CLSID"): # Eeek - no makepy support - try and build it.
try:
ti = disp._oleobj_.GetTypeInfo()
disp_clsid = ti.GetTypeAttr()[0]
tlb, index = ti.GetContainingTypeLib()
tla = tlb.GetLibAttr()
mod = EnsureModule(tla[0], tla[1], tla[3], tla[4], bForDemand=bForDemand)
GetModuleForCLSID(disp_clsid)
# Get the class from the module.
import CLSIDToClass
disp_class = CLSIDToClass.GetClass(str(disp_clsid))
disp = disp_class(disp._oleobj_)
except pythoncom.com_error:
raise TypeError("This COM object can not automate the makepy process - please run makepy manually for this object")
return disp
def WriteClassHeader(self, generator):
generator.checkWriteDispatchBaseClass()
doc = self.doc
stream = generator.file
print >> stream, 'class ' + self.python_name + '(DispatchBaseClass):'
if doc[1]: print >> stream, '\t' + build._makeDocString(doc[1])
try:
progId = pythoncom.ProgIDFromCLSID(self.clsid)
print >> stream, "\t# This class is creatable by the name '%s'" % (progId)
except pythoncom.com_error:
pass
print >> stream, "\tCLSID = " + repr(self.clsid)
if self.coclass_clsid is None:
print >> stream, "\tcoclass_clsid = None"
else:
print >> stream, "\tcoclass_clsid = " + repr(self.coclass_clsid)
print >> stream
self.bWritten = 1
def _Build_CoClass(self, type_info_tuple):
info, infotype, doc, attr = type_info_tuple
# find the source and dispinterfaces for the coclass
child_infos = []
for j in range(attr[8]):
flags = info.GetImplTypeFlags(j)
try:
refType = info.GetRefTypeInfo(info.GetRefTypeOfImplType(j))
except pythoncom.com_error:
# Can't load a dependent typelib?
continue
refAttr = refType.GetTypeAttr()
child_infos.append( (info, refAttr.typekind, refType, refType.GetDocumentation(-1), refAttr, flags) )
# Done generating children - now the CoClass itself.
newItem = CoClassItem(info, attr, doc)
return newItem, child_infos
def __init__(self, oobj=None):
if oobj is None:
oobj = pythoncom.new(self.CLSID)
elif isinstance(oobj, DispatchBaseClass):
try:
oobj = oobj._oleobj_.QueryInterface(self.CLSID, pythoncom.IID_IDispatch) # Must be a valid COM instance
except pythoncom.com_error, details:
import winerror
# Some stupid objects fail here, even tho it is _already_ IDispatch!!??
# Eg, Lotus notes.
# So just let it use the existing object if E_NOINTERFACE
if details.hresult != winerror.E_NOINTERFACE:
raise
oobj = oobj._oleobj_
self.__dict__["_oleobj_"] = oobj # so we dont call __setattr__
# Provide a prettier name than the CLSID
def test():
import win32com.client
oldcwd = os.getcwd()
try:
session = gencache.EnsureDispatch("MAPI.Session")
try:
session.Logon(GetDefaultProfileName())
except pythoncom.com_error, details:
print "Could not log on to MAPI:", details
return
except pythoncom.error:
# no mapi.session - let's try outlook
app = gencache.EnsureDispatch("Outlook.Application")
session = app.Session
try:
TestUser(session)
TestAddress(session)
DumpFolders(session)
finally:
session.Logoff()
# It appears Exchange will change the cwd on us :(
os.chdir(oldcwd)
def TestDynamic():
progress("Testing Dynamic")
import win32com.client.dynamic
o = win32com.client.dynamic.DumbDispatch("PyCOMTest.PyCOMTest")
TestCommon(o, False)
counter = win32com.client.dynamic.DumbDispatch("PyCOMTest.SimpleCounter")
TestCounter(counter, False)
# Dynamic doesn't know this should be an int, so we get a COM
# TypeMismatch error.
try:
check_get_set_raises(ValueError, o.GetSetInt, "foo")
raise error("no exception raised")
except pythoncom.com_error, exc:
if exc.hresult != winerror.DISP_E_TYPEMISMATCH:
raise
# damn - props with params don't work for dynamic objects :(
# o.SetParamProp(0, 1)
# if o.ParamProp(0) != 1:
# raise RuntimeError, o.paramProp(0)
def DispExTest(ob):
if not __debug__: print "WARNING: Tests dressed up as assertions are being skipped!"
assert ob.GetDispID("Add", 0)==10, "Policy did not honour the dispid"
# Not impl
# assert ob.GetMemberName(10, 0)=="add", "Policy did not give me the correct function for the dispid"
assert ob.GetDispID("Remove", 0)==11, "Policy did not honour the dispid"
assert ob.GetDispID("In", 0)==1000, "Allocated dispid unexpected value"
assert ob.GetDispID("_NewEnum", 0)==pythoncom.DISPID_NEWENUM, "_NewEnum() got unexpected DISPID"
dispids = []
dispid = -1
while 1:
try:
dispid = ob.GetNextDispID(0, dispid)
dispids.append(dispid)
except pythoncom.com_error, (hr, desc, exc, arg):
assert hr==winerror.S_FALSE, "Bad result at end of enum"
break
dispids.sort()
if dispids != [pythoncom.DISPID_EVALUATE, pythoncom.DISPID_NEWENUM, 10, 11, 1000]:
raise Error("Got back the wrong dispids: %s" % dispids)
def testit(self):
ctx = pythoncom.CreateBindCtx()
rot = pythoncom.GetRunningObjectTable()
num = 0
for mk in rot:
name = mk.GetDisplayName(ctx, None)
num += 1
# Monikers themselves can iterate their contents (sometimes :)
try:
for sub in mk:
num += 1
except pythoncom.com_error, exc:
if exc.hresult != winerror.E_NOTIMPL:
raise
#if num < 2:
# print "Only", num, "objects in the ROT - this is unusual"
def testShellLink(self):
desktop = str(shell.SHGetSpecialFolderPath(0, CSIDL_DESKTOP))
num = 0
shellLink = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
persistFile = shellLink.QueryInterface(pythoncom.IID_IPersistFile)
names = [os.path.join(desktop, n) for n in os.listdir(desktop)]
programs = str(shell.SHGetSpecialFolderPath(0, CSIDL_PROGRAMS))
names.extend([os.path.join(programs, n) for n in os.listdir(programs)])
for name in names:
try:
persistFile.Load(name,STGM_READ)
except pythoncom.com_error:
continue
# Resolve is slow - avoid it for our tests.
#shellLink.Resolve(0, shell.SLR_ANY_MATCH | shell.SLR_NO_UI)
fname, findData = shellLink.GetPath(0)
unc = shellLink.GetPath(shell.SLGP_UNCPRIORITY)[0]
num += 1
if num == 0:
# This isn't a fatal error, but is unlikely.
print "Could not find any links on your desktop or programs dir, which is unusual"
def _WaitForFinish(ob, timeout):
end = time.time() + timeout
while 1:
if msvcrt.kbhit():
msvcrt.getch()
break
pythoncom.PumpWaitingMessages()
stopEvent.wait(.2)
if stopEvent.isSet():
stopEvent.clear()
break
try:
if not ob.Visible:
# Gone invisible - we need to pretend we timed
# out, so the app is quit.
return 0
except pythoncom.com_error:
# Excel is busy (eg, editing the cell) - ignore
pass
if time.time() > end:
return 0
return 1
def OnConnection(self, application, connectMode, addin, custom):
print "OnConnection", application, connectMode, addin, custom
try:
self.appHostApp = application
cbcMyBar = self.appHostApp.CommandBars.Add(Name="PythonBar", Position=constants.msoBarTop, MenuBar=constants.msoBarTypeNormal, Temporary=True)
btnMyButton = cbcMyBar.Controls.Add(Type=constants.msoControlButton, Parameter="Greetings")
btnMyButton=self.toolbarButton = DispatchWithEvents(btnMyButton, ButtonEvent)
btnMyButton.Style = constants.msoButtonCaption
btnMyButton.BeginGroup = True
btnMyButton.Caption = "&Python"
btnMyButton.TooltipText = "Python rules the World"
btnMyButton.Width = "34"
cbcMyBar.Visible = True
except pythoncom.com_error, (hr, msg, exc, arg):
print "The Excel call failed with code %d: %s" % (hr, msg)
if exc is None:
print "There is no extended error information"
else:
wcode, source, text, helpFile, helpId, scode = exc
print "The source of the error is", source
print "The error message is", text
print "More info can be found in %s (id=%d)" % (helpFile, helpId)
def close(self, del_object=True):
"""Disconnect from the currently connected OPC server"""
try:
self.remove(self.groups())
except pythoncom.com_error, err:
error_msg = 'Disconnect: %s' % self._get_error_str(err)
raise OPCError, error_msg
except OPCError:
pass
finally:
if self.trace: self.trace('Disconnect()')
self._opc.Disconnect()
# Remove this object from the open gateway service
if self._open_serv and del_object:
self._open_serv.release_client(self._open_self)
def _bind_to_filter(self, fileName):
"""
See if the file is a structured storage file or a normal file
and then return an ifilter interface by calling the appropriate bind/load function
"""
if pythoncom.StgIsStorageFile(fileName):
self.stg = pythoncom.StgOpenStorage(fileName, None, storagecon.STGM_READ | storagecon.STGM_SHARE_DENY_WRITE)
try:
self.f = ifilter.BindIFilterFromStorage(self.stg)
except pythoncom.com_error, e:
if e[0] == -2147467262: # 0x80004002: # no interface, try the load interface (this happens for some MSoft files)
self.f = ifilter.LoadIFilter(fileName)
else:
raise
else:
self.f = ifilter.LoadIFilter(fileName)
self.stg = None
def _get_properties(self, properties):
"""
Use OLE property sets to get base properties
"""
try:
pss = self.stg.QueryInterface(pythoncom.IID_IPropertySetStorage )
except pythoncom.com_error, e:
self._trace('No Property information could be retrieved', e)
return
ps = pss.Open(PSGUID_SUMMARYINFORMATION)
props = (PIDSI_TITLE, PIDSI_SUBJECT, PIDSI_AUTHOR, PIDSI_KEYWORDS, PIDSI_COMMENTS)
title, subject, author, keywords, comments = ps.ReadMultiple(props)
if title is not None:
properties['title'] = title
if subject is not None:
properties['description'] = subject
if author is not None:
properties['author'] = author
if keywords is not None:
properties['keywords'] = keywords
if comments is not None:
properties['comments'] = comments