I am writing a python wrapper to the Microsoft Dynamics Business Connector .net assembly.
This is my code:
"""Implements wrapper for axapta business connector."""
import pathlib
from msl.loadlib import LoadLibrary
import clr
DLL_PATH = pathlib.Path(__file__).parent / 'Microsoft.Dynamics.BusinessConnectorNet.dll'
def test_msl_connector():
"""Get Axapta object via msl-loadlib package."""
connectorLL = LoadLibrary(DLL_PATH, 'net')
Axapta = getattr(connectorLL.lib,
'Microsoft.Dynamics.BusinessConnectorNet').Axapta
return Axapta
def test_pure_pythonnet_connector():
"""Get Axapta object via pythonnet package."""
clr.AddReference(str(DLL_PATH))
from Microsoft.Dynamics.BusinessConnectorNet import Axapta
return Axapta
This is my errors when running pytest:
============================= test session starts =============================
platform win32 -- Python 3.6.2, pytest-3.4.0, py-1.5.2, pluggy-0.6.0
rootdir: C:\Users\AZ\Desktop\test_bom-mcs, inifile:
collected 2 items
test_main.py FF [100%]
================================== FAILURES ===================================
_____________________________ test_msl_connector ______________________________
def test_msl_connector():
"""Get Axapta object via msl-loadlib package."""
> connectorLL = LoadLibrary(DLL_PATH, 'net')
test_main.py:12:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'LoadLibrary' object has no attribute '_lib'") raised in repr()] LoadLibrary object at 0
x4152c18>
path = WindowsPath('C:/Users/AZ/Desktop/test_bom-mcs/Microsoft.Dynamics.BusinessConnectorNet.dll')
libtype = 'net'
def __init__(self, path, libtype='cdll'):
_path = path
# a reference to the .NET Runtime Assembly
self._assembly = None
# assume a default extension if no extension was provided
if not os.path.splitext(_path)[1]:
_path += DEFAULT_EXTENSION
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 IOError('Cannot find the shared library "{}"'.format(path))
if libtype == 'cdll':
self._lib = ctypes.CDLL(self._path)
elif libtype == 'windll':
self._lib = ctypes.WinDLL(self._path)
elif libtype == 'oledll':
self._lib = ctypes.OleDLL(self._path)
elif libtype == 'net' and self.is_pythonnet_installed():
import clr
try:
# By default, pythonnet can only load libraries that are for .NET 4.0+.
#
# When MSL-LoadLib is installed, the useLegacyV2RuntimeActivationPolicy
# property should have been enabled automatically to allow for loading
# assemblies from previous .NET Framework versions.
self._assembly = clr.System.Reflection.Assembly.LoadFile(self._path)
except clr.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. "
#
# To solve this problem, a <python-executable>.config file must exist and it must
# contain a useLegacyV2RuntimeActivationPolicy property that is set to be "true".
if "Mixed mode assembly" in str(err):
status, msg = self.check_dot_net_config(sys.executable)
if not status == 0:
raise IOError(msg)
else:
update_msg = 'Checking .NET config returned "{}" '.format(msg)
update_msg += 'and still cannot load library.\n'
update_msg += str(err)
raise IOError(update_msg)
raise IOError('The above "System.IO.FileLoadException" is not handled.\n')
# the shared library must be available in sys.path
head, tail = os.path.split(self._path)
sys.path.insert(0, head)
# don't include the library extension
clr.AddReference(os.path.splitext(tail)[0])
# import namespaces, create instances of classes or reference a System.Type[] object
dotnet = {}
> for t in self._assembly.GetTypes():
E System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Ret
rieve the LoaderExceptions property for more information.
E at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
E at System.Reflection.Assembly.GetTypes()
..\..\.virtualenvs\test_bom-mcs-bwfslhpz\lib\site-packages\msl\loadlib\load_library.py:132: ReflectionTypeLoadExc
eption
________________________ test_pure_pythonnet_connector ________________________
def test_pure_pythonnet_connector():
"""Get Axapta object via pythonnet package."""
clr.AddReference(str(DLL_PATH))
> from Microsoft.Dynamics.BusinessConnectorNet import Axapta
E ModuleNotFoundError: No module named 'Microsoft'
test_main.py:21: ModuleNotFoundError
========================== 2 failed in 0.61 seconds ===========================
P.S. The stackoverflow grader asks me to add more details:)
What else - obj = clr.AddRefrence
works and I can see a Microsoft attribute in obj
. But no any Dynamics
etc.
Repository for this example is here https://gitlab.com/remak_team/open-source/MicrosoftDynamicsConnector_python_wrapper/tree/master
This exception relates to the Microsoft.Dynamics.BusinessConnectorNet.dll
library not finding all of the required dependencies.
On a computer that was successfully able to load this library I used Dependency Walker and DependencyWalker for .NET to create a file that contains the full path to all of the dependencies that these two Walker's found. The list of dependencies that are required can be downloaded here.
Hopefully, you will be able to locate the missing dependencies from this list and then you will be able to load the Microsoft.Dynamics.BusinessConnectorNet.dll
library.