在python中包装Microsoft Dynamics Business Connector .net程序集

时间:2018-02-07 10:43:44

标签: python .net windows axapta python.net

我正在为Microsoft Dynamics Business Connector .net程序集编写一个python包装器。

这是我的代码:

"""Implements wrapper for axapta bussiness 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

运行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 ===========================

.net反编译器显示: a picture from ilspy

P.S。 stackoverflow分级器要求我添加更多细节:) 还有什么 - obj = clr.AddRefrence有效,我可以在obj中看到Microsoft属性。但没有任何Dynamics等。

此示例的存储库位于 https://gitlab.com/remak_team/open-source/MicrosoftDynamicsConnector_python_wrapper/tree/master

1 个答案:

答案 0 :(得分:2)

此异常与Microsoft.Dynamics.BusinessConnectorNet.dll库未找到所有必需的依赖项有关。

在成功加载此库的计算机上,我使用Dependency WalkerDependencyWalker for .NET创建了一个文件,其中包含这两个Walker发现的所有依赖项的完整路径。可以下载here所需的依赖项列表。

希望您能够从此列表中找到缺少的依赖项,然后您就可以加载Microsoft.Dynamics.BusinessConnectorNet.dll库。