def test(self): self.failUnlessEqual(GUID(), GUID()) self.failUnlessEqual( GUID("{00000000-0000-0000-C000-000000000046}"), GUID("{00000000-0000-0000-C000-000000000046}") ) self.failUnlessEqual( str(GUID("{0002DF01-0000-0000-C000-000000000046}")), "{0002DF01-0000-0000-C000-000000000046}" ) self.failUnlessEqual( repr(GUID("{0002DF01-0000-0000-C000-000000000046}")), 'GUID("{0002DF01-0000-0000-C000-000000000046}")' ) self.assertRaises(WindowsError, GUID, "abc") self.assertRaises(WindowsError, GUID.from_progid, "abc") self.assertRaises(WindowsError, lambda guid: guid.as_progid(), GUID("{00000000-0000-0000-C000-000000000046}")) if os.name == "nt": self.failUnlessEqual( GUID.from_progid("InternetExplorer.Application"), GUID("{0002DF01-0000-0000-C000-000000000046}") ) self.failUnlessEqual( GUID("{0002DF01-0000-0000-C000-000000000046}").as_progid(), u"InternetExplorer.Application.1" ) elif os.name == "ce": self.failUnlessEqual(GUID.from_progid("JScript"), GUID("{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}")) self.failUnlessEqual(GUID("{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}").as_progid(), u"JScript") self.failIfEqual(GUID.create_new(), GUID.create_new())
def test(self): self.failUnlessEqual(GUID(), GUID()) self.failUnlessEqual(GUID("{00000000-0000-0000-C000-000000000046}"), GUID("{00000000-0000-0000-C000-000000000046}")) self.failUnlessEqual( str(GUID("{0002DF01-0000-0000-C000-000000000046}")), "{0002DF01-0000-0000-C000-000000000046}") self.failUnlessEqual( repr(GUID("{0002DF01-0000-0000-C000-000000000046}")), 'GUID("{0002DF01-0000-0000-C000-000000000046}")') self.assertRaises(WindowsError, GUID, "abc") self.assertRaises(WindowsError, GUID.from_progid, "abc") self.assertRaises(WindowsError, lambda guid: guid.as_progid(), GUID("{00000000-0000-0000-C000-000000000046}")) if os.name == "nt": self.failUnlessEqual( GUID.from_progid("InternetExplorer.Application"), GUID("{0002DF01-0000-0000-C000-000000000046}")) self.failUnlessEqual( GUID("{0002DF01-0000-0000-C000-000000000046}").as_progid(), u'InternetExplorer.Application.1') elif os.name == "ce": self.failUnlessEqual( GUID.from_progid("JScript"), GUID("{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}")) self.failUnlessEqual( GUID("{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}").as_progid(), u'JScript') self.failIfEqual(GUID.create_new(), GUID.create_new())
def available(): if not sys.platform.lower().startswith('win'): return False try: from comtypes import GUID GUID.from_progid('FreedomSci.JawsApi' ) #If we fail on this, we haven't loaded anything from comtypes.client import CreateObject test = CreateObject("FreedomSci.JawsApi") return test.SayString("", False) except: return False return True
def __excel_app_from_hwnd(window_h): """ comtypes library is used to search windows handles for Excel application, then converts that pointer to a pywin object thru __comtype_to_pywin_obj() sometimes, non-Excel applications are running under the same window_h as an Excel process, like "print driver host for applications" these will fail to return a valid excel7_wnd for FindWindowEx, but killing these processes will also bring down the Excel application, which is not neccessarily corrupt """ global corrupt_hwnds if window_h in corrupt_hwnds: return None desk_wnd = FindWindowEx(window_h, None, xl_desk_class, None) excel7_wnd = FindWindowEx(desk_wnd, None, xl_excel7_class, None) if excel7_wnd == 0: corrupt_hwnds.add(window_h) if __is_excel_process(window_h): __kill_task(window_h) return None cls_id = GUID.from_progid(xl_clsid) obj_ptr = ctypes.POINTER(IDispatch)() AccessibleObjectFromWindow(excel7_wnd, native_om, byref(cls_id), byref(obj_ptr)) window = Dispatch(obj_ptr) try: com_obj = window.application excel_app = __comtype_to_pywin_obj(com_obj, IDispatch) excel_app = pywin_dispatch(excel_app) excel_app.Visible = True return excel_app except (COMError, com_error, NameError) as e: raise ChildProcessError( 'remote procedure call to Excel application rejected\n' '(check if cursor is still active within a cell somewhere, ' 'Excel will reject automation calls while waiting on ' 'user input)') from e
def test(self): self.assertEqual(GUID(), GUID()) self.assertEqual(GUID("{00000000-0000-0000-C000-000000000046}"), GUID("{00000000-0000-0000-C000-000000000046}")) self.assertEqual(str(GUID("{0002DF01-0000-0000-C000-000000000046}")), "{0002DF01-0000-0000-C000-000000000046}") self.assertEqual(repr(GUID("{0002DF01-0000-0000-C000-000000000046}")), 'GUID("{0002DF01-0000-0000-C000-000000000046}")') self.assertRaises(WindowsError, GUID, "abc") self.assertRaises(WindowsError, GUID.from_progid, "abc") self.assertRaises(WindowsError, lambda guid: guid.as_progid(), GUID("{00000000-0000-0000-C000-000000000046}")) if os.name == "nt": self.assertEqual(GUID.from_progid("InternetExplorer.Application"), GUID("{0002DF01-0000-0000-C000-000000000046}")) self.assertEqual( GUID("{0002DF01-0000-0000-C000-000000000046}").as_progid(), 'InternetExplorer.Application.1') self.assertNotEqual(GUID.create_new(), GUID.create_new())
def load(activex_id, parent=None, x=0, y=0, width=0, height=0, style=0, ex_style=0): """Load an ActiveX library. Additional information about the keyword arguments are described by the CreateWindowExA_ object. Loading an ActiveX library requires comtypes_ to be installed. .. _comtypes: https://pypi.org/project/comtypes/ .. _CreateWindowExA: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa .. _System.Windows.Forms: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms Parameters ---------- activex_id : :class:`str` The ProgID or CLSID of the ActiveX object. parent The parent or owner window of the window being created. The parent is typically an object from the System.Windows.Forms_ namespace that has a ``Handle`` property. x : :class:`int`, optional The initial horizontal position of the window. y : :class:`int`, optional The initial vertical position of the window. width : :class:`int`, optional The width of the window. height : :class:`int`, optional The height of the window. style : :class:`int`, optional The style of the window being created. This argument can be a combination of the `Window Styles`_ constants, e.g., ``style = WS_CHILD | WS_VISIBLE``. ex_style : :class:`int`, optional The extended window style of the window being created. This argument can be a combination of the `Extended Window Styles`_ constants, e.g., ``ex_style = WS_EX_APPWINDOW | WS_EX_CONTEXTHELP``. Returns ------- The interface pointer to the ActiveX library. Raises ------ OSError If the library cannot be loaded. """ if GUID is None: raise OSError( 'Cannot load an ActiveX library because comtypes is not installed.\n' 'Run: pip install comtypes') try: clsid = GUID.from_progid(activex_id) except (TypeError, OSError): clsid = None if clsid is None: raise OSError( "Cannot find '{}' for libtype='activex'".format(activex_id)) if parent is not None: try: parent_handle = parent.Handle.ToInt32() except AttributeError: parent_handle = None if parent_handle is None: raise OSError( 'Cannot create a Handle from the parent {}'.format( type(parent))) else: parent_handle = None # calling AtlAxWinInit initializes ATL's control hosting code # by registering the "AtlAxWin" window class so that this window # class is available to the CreateWindowExA function h_result = ctypes.windll.atl.AtlAxWinInit() if not h_result: raise OSError('Cannot register the "AtlAxWin" window class') # create a new window h_instance = ctypes.windll.kernel32.GetModuleHandleA(None) hwnd = ctypes.windll.user32.CreateWindowExA( ex_style, # dwExStyle b'AtlAxWin', # lpClassName str(clsid).encode(), # lpWindowName style, # dwStyle x, # X y, # Y width, # nWidth height, # nHeight parent_handle, # hWndParent None, # hMenu h_instance, # hInstance 0 # lpParam ) if hwnd == 0: raise OSError('CreateWindowExA {}'.format(ctypes.WinError())) # get the interface to the ActiveX control unknown = ctypes.POINTER(IUnknown)() ret = ctypes.windll.atl.AtlAxGetControl(hwnd, ctypes.byref(unknown)) if ret != 0: raise OSError('AtlAxGetControl {}'.format(ctypes.WinError())) return GetBestInterface(unknown)
def check(cls): try: GUID.from_progid(COM_CLASS) return True except WindowsError: return False
# This test requires that the Agilent IVI-COM Driver for Agilent546XX # is installed. It is not requires to have a physical instrument # connected, the driver is used in simulation mode. import unittest from comtypes.test import ResourceDenied from comtypes.client import CreateObject from comtypes import GUID from comtypes.safearray import _midlSAFEARRAY from ctypes import c_double, POINTER try: GUID.from_progid("Agilent546XX.Agilent546XX") except WindowsError: pass else: class Test(unittest.TestCase): def test(self): # The point of this test is the ReadWaveform method below, # which takes several [in, out] arguments. agDrvr = CreateObject("Agilent546XX.Agilent546XX") # XXX XXX XXX The following call crashes hard with an accessviolation when # the OANOCACHE environ variable is set. import os if "OANOCACHE" in os.environ: print "Cannot test. buggy COM object?" return # Initialize the driver in simulation mode. Resource descriptor is ignored. agDrvr.Initialize("", False, False, "Simulate=true")
import unittest from ctypes import POINTER from comtypes.automation import IDispatch from comtypes.client import CreateObject from comtypes import GUID ##from test import test_support ##from comtypes.unittests import support try: GUID.from_progid("MSScriptControl.ScriptControl") CreateObject("MSScriptControl.ScriptControl") except WindowsError: # doesn't exist on Windows CE or in 64-bit. pass else: class Test(unittest.TestCase): def test_jscript(self): engine = CreateObject("MSScriptControl.ScriptControl") engine.Language = "JScript" # strange. # # engine.Eval returns a VARIANT containing a dispatch pointer. # # The dispatch pointer exposes this typeinfo (the number of # dispproperties varies, depending on the length of the list we pass # to Eval): # #class JScriptTypeInfo(comtypes.gen._00020430_0000_0000_C000_000000000046_0_2_0.IDispatch): # 'JScript Type Info'
def check(cls): try: GUID.from_progid(COM_CLASS) return True except comtypes.COMError: return False
def __init__(self, path, libtype=None, **kwargs): """Load a shared library. For example, a C/C++, FORTRAN, C#, Java, Delphi, LabVIEW, ActiveX, ... library. .. versionchanged:: 0.4 Added support for Java archives. .. versionchanged:: 0.5 Added support for COM_ libraries. .. versionchanged:: 0.9 Added support for ActiveX_ libraries. .. _Assembly: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly .. _comtypes.CreateObject: https://pythonhosted.org/comtypes/#creating-and-accessing-com-objects .. _COM: https://en.wikipedia.org/wiki/Component_Object_Model .. _ActiveX: https://en.wikipedia.org/wiki/ActiveX Parameters ---------- path : :class:`str` The path to the shared library. The search order for finding the shared library is: 1. assume that a full or a relative (to the current working directory) path is specified, 2. use :func:`ctypes.util.find_library` to find the shared library file, 3. search :data:`sys.path`, then 4. search :data:`os.environ['PATH'] <os.environ>` to find the shared library. If loading a COM_ library then `path` is either the `ProgID`, e.g. ``"InternetExplorer.Application"``, or the `CLSID`, e.g. ``"{2F7860A2-1473-4D75-827D-6C4E27600CAC}"``. libtype : :class:`str`, optional The library type. The following values are currently supported: * ``'cdll'`` -- for a library that uses the __cdecl calling convention * ``'windll'`` or ``'oledll'`` -- for a __stdcall calling convention * ``'net'`` or ``'clr'`` -- for Microsoft's .NET Framework (Common Language Runtime) * ``'java'`` -- for a Java archive, ``.jar``, or Java byte code, ``.class``, file * ``'com'`` -- for a COM_ library * ``'activex'`` -- for an ActiveX_ library Default is ``'cdll'``. .. tip:: Since the ``.jar`` or ``.class`` extension uniquely defines a Java library, the `libtype` will be automatically set to ``'java'`` if `path` ends with ``.jar`` or ``.class``. **kwargs All additional keyword arguments are passed to the object that loads the library. If `libtype` is * ``'cdll'`` then :class:`~ctypes.CDLL` * ``'windll'`` then :class:`~ctypes.WinDLL` * ``'oledll'`` then :class:`~ctypes.OleDLL` * ``'net'`` or ``'clr'`` then all keyword arguments are ignored * ``'java'`` then :class:`~.py4j.java_gateway.JavaGateway` * ``'com'`` then comtypes.CreateObject_ * ``'activex'`` then :meth:`Application.load <msl.loadlib.activex.Application.load>` Raises ------ OSError If the shared library cannot be loaded. ValueError If the value of `libtype` is not supported. """ # a reference to the shared library self._lib = None # a reference to the .NET Runtime Assembly self._assembly = None # a reference to the Py4J JavaGateway self._gateway = None if not path: raise ValueError( 'You must specify the path, got {!r}'.format(path)) # fixes Issue #8, if `path` is a <class 'pathlib.Path'> object if hasattr(path, 'as_posix'): path = path.as_posix() # try to automatically determine the libtype if libtype is None: if path.endswith('.jar') or path.endswith('.class'): libtype = 'java' else: libtype = 'cdll' else: libtype = libtype.lower() if libtype not in LoadLibrary.LIBTYPES: raise ValueError('Cannot load libtype={!r}.\n' 'Must be one of: {}'.format( libtype, ', '.join(LoadLibrary.LIBTYPES))) # create a new reference to `path` just in case the # DEFAULT_EXTENSION is appended below so that the # ctypes.util.find_library function call will use the # unmodified value of `path` _path = path # assume a default extension if no extension was provided ext = os.path.splitext(path)[1] if not ext and libtype not in ['java', 'com', 'activex']: _path += DEFAULT_EXTENSION if IS_PYTHON2: _path = _path.encode(_encoding) if libtype not in ['com', 'activex']: self._path = os.path.abspath(_path) if not os.path.isfile(self._path): # for find_library use the original 'path' value since it may be a library name # without any prefix like 'lib', suffix like '.so', '.dylib' or version number self._path = ctypes.util.find_library(path) if self._path is None: # then search sys.path and os.environ['PATH'] success = False search_dirs = sys.path + os.environ['PATH'].split( os.pathsep) for directory in search_dirs: p = os.path.join(directory, _path) if os.path.isfile(p): self._path = p success = True break if not success: raise OSError( "Cannot find '{}' for libtype='{}'".format( path, libtype)) else: self._path = _path if libtype == 'cdll': self._lib = ctypes.CDLL(self._path, **kwargs) elif libtype == 'windll': self._lib = ctypes.WinDLL(self._path, **kwargs) elif libtype == 'oledll': self._lib = ctypes.OleDLL(self._path, **kwargs) elif libtype == 'com': if not utils.is_comtypes_installed(): raise OSError( 'Cannot load a COM library because comtypes is not installed.\n' 'Run: pip install comtypes') from comtypes import GUID from comtypes.client import CreateObject try: clsid = GUID.from_progid(self._path) except (TypeError, OSError): clsid = None if clsid is None: raise OSError( "Cannot find '{}' for libtype='com'".format(path)) self._lib = CreateObject(clsid, **kwargs) elif libtype == 'activex': from .activex import Application self._lib = Application.load(self._path, **kwargs) elif libtype == 'java': if not utils.is_py4j_installed(): raise OSError( 'Cannot load a Java file because Py4J is not installed.\n' 'Run: pip install py4j') from py4j.version import __version__ from py4j.java_gateway import JavaGateway, GatewayParameters # the address and port to use to host the py4j.GatewayServer address = kwargs.pop('address', '127.0.0.1') port = kwargs.pop('port', utils.get_available_port()) # find the py4j*.jar file (needed to import the py4j.GatewayServer on the Java side) filename = 'py4j' + __version__ + '.jar' py4j_jar = os.environ.get('PY4J_JAR') if py4j_jar: if not os.path.isfile( py4j_jar) or os.path.basename(py4j_jar) != filename: raise OSError( 'A PY4J_JAR environment variable exists, ' 'but the full path to the {} file is invalid\n' 'PY4J_JAR={}'.format(filename, py4j_jar)) else: root = os.path.dirname(sys.executable) for item in [ root, os.path.dirname(root), os.path.join(os.path.expanduser('~'), '.local') ]: py4j_jar = os.path.join(item, 'share', 'py4j', filename) if os.path.isfile(py4j_jar): break if not os.path.isfile(py4j_jar): raise OSError( 'Cannot find {0}\nCreate a PY4J_JAR environment ' 'variable to be equal to the full path to {0}'.format( filename)) # build the java command wrapper = os.path.join(os.path.dirname(__file__), 'py4j-wrapper.jar') cmd = [ 'java', '-cp', py4j_jar + os.pathsep + wrapper, 'Py4JWrapper', str(port) ] # from the URLClassLoader documentation: # Any URL that ends with a '/' is assumed to refer to a directory. Otherwise, the URL # is assumed to refer to a JAR file which will be downloaded and opened as needed. if ext == '.jar': cmd.append(self._path) else: # it is a .class file cmd.append(os.path.dirname(self._path) + '/') err = None try: # start the py4j.GatewayServer flags = 0x08000000 if IS_WINDOWS else 0 # fixes issue 31, CREATE_NO_WINDOW = 0x08000000 subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, creationflags=flags) except OSError as e: err = str(e).rstrip() err += '\nYou must have a Java Runtime Environment installed and available on PATH' if err: raise OSError(err) try: utils.wait_for_server(address, port, 10.0) except OSError as e: err = str(e).rstrip() err += '\nCould not start the Py4J GatewayServer' if err: raise OSError(err) self._gateway = JavaGateway(gateway_parameters=GatewayParameters( address=address, port=port, **kwargs)) self._lib = self._gateway.jvm elif libtype == 'net' or libtype == 'clr': if not utils.is_pythonnet_installed(): raise OSError( 'Cannot load a .NET Assembly because pythonnet is not installed.\n' 'Run: pip install pythonnet') import clr import System dotnet = {'System': System} # the shared library must be available in sys.path head, tail = os.path.split(self._path) sys.path.insert(0, head) try: # don't include the library extension clr.AddReference(os.path.splitext(tail)[0]) except (System.IO.FileNotFoundException, System.IO.FileLoadException): # The file must exist since its existence is checked above. # There must be another reason why loading the DLL raises this # error. Calling LoadFile (below) provides more information # in the error message. pass try: # By default, pythonnet can only load libraries that are for .NET 4.0+ # # In order to allow pythonnet to load a library from .NET <4.0 the # useLegacyV2RuntimeActivationPolicy property needs to be enabled # in a <python-executable>.config file. If the following statement # raises a FileLoadException then attempt to create the configuration # file that has the property enabled and then notify the user why # loading the library failed and ask them to re-run their Python # script to load the .NET library. self._assembly = System.Reflection.Assembly.LoadFile( self._path) except System.IO.FileLoadException as err: # Example error message that can occur if the library is for .NET <4.0, # and the useLegacyV2RuntimeActivationPolicy is not enabled: # # " Mixed mode assembly is built against version 'v2.0.50727' of the # runtime and cannot be loaded in the 4.0 runtime without additional # configuration information. " if str(err).startswith( 'Mixed mode assembly is built against version'): status, msg = utils.check_dot_net_config(sys.executable) if not status == 0: raise OSError(msg) else: update_msg = 'Checking .NET config returned "{}" '.format( msg) update_msg += 'and still cannot load library.\n' update_msg += str(err) raise OSError(update_msg) raise OSError( 'The above "System.IO.FileLoadException" is not handled.\n' ) try: types = self._assembly.GetTypes() except Exception as e: utils.logger.error(e) utils.logger.error('The LoaderExceptions are:') for item in e.LoaderExceptions: utils.logger.error(' ' + item.Message) else: for t in types: try: if t.Namespace: obj = __import__(t.Namespace) else: obj = getattr(__import__('clr'), t.FullName) except: obj = t obj.__name__ = t.FullName if obj.__name__ not in dotnet: dotnet[obj.__name__] = obj self._lib = DotNet(dotnet, self._path) else: assert False, 'Should not get here -- contact developers' if IS_PYTHON2: self._path = self._path.decode(_encoding) utils.logger.debug('Loaded ' + self._path)