1

I have an application that relies on NuGet's <bindingRedirect> feature to ensure a single version of log4net.dll. Binding redirects are automatically added to the applications app.config file.

I'd like to load that application's assemblies into Python and call into its code, but because the binding redirects are application-specific, they're not being picked up by Pythonnet and the assembly fails to load:

LOG: Post-policy reference: log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a
[...snip...]
LOG: Assembly Name is: log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a
WRN: Comparing the assembly name resulted in the mismatch: Major Version

Can I get pythonnet to refer to my application's app.config and use the <bindingRedirect> found there? Or can I apply a binding redirect after startup, without needing an app.config?

Tim Robinson
  • 53,480
  • 10
  • 121
  • 138

3 Answers3

2

Here is how to enable app.config with pythonnet when using .NET assemblies from CPython:

Place python.exe.config file next python.exe with the following configuration for detection later:

<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="customAppSettingsGroup"> <section name="customAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration" /> </sectionGroup> </configSections> <customAppSettingsGroup> <customAppSettings> <add key="Debugger" value="True"/> </customAppSettings> </customAppSettingsGroup> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/> </startup> </configuration>

Generate .NET assembly with the following code for testing and reading app.config settings:

using System;

using System.Collections.Specialized;
using System.Configuration;

namespace dotnet20
{
    public class Class1
    {
        public Class1()
        {
            NameValueCollection settings =
                ConfigurationManager.GetSection("customAppSettingsGroup/customAppSettings") as NameValueCollection;

            if (settings != null)
            {
                foreach (string key in settings.AllKeys)
                {
                    if ((key == "Debugger") && (settings[key] == "True"))
                    {
                        Console.WriteLine("Detected debugger mode");
                    }
                }
            }
        }
    }
}

Now test that pythonnet is able to detect these custom settings from app.config:

python
Python 3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import clr
>>> import sys
>>> sys.path.append(r"C:\pythonnet\dotnet2.0\bin\Debug")
>>> clr.AddReference("dotnet2.0")
<System.Reflection.RuntimeAssembly object at 0x000001A51626D630>
>>> from dotnet20 import Class1
>>> Class1()
Detected debugger mode
<dotnet20.Class1 object at 0x000001A51626D6A0>
>>>
denfromufa
  • 5,610
  • 13
  • 81
  • 138
0

I have got into similar problem using Pythonnet with .net dLLs.

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=3.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' or one of its dependencies. The system cannot find the file specified.

I didn't have Version 3.1.0.0 of Microsoft.Extensions.DependencyInjection.Abstractions and hence the error. My .net project has app.config file which was pointing to a newer version of this dependency ( 3.1.5.0) [ bindingRedirect ]

The solution was to use this app.config file from .net project, rename it to python.exe.config and put it in the same folder where python.exe is. I am not sure if this is the best solution but i have looked in to a bunch of other solutions and this only seems to be working.

above_c_level
  • 3,579
  • 3
  • 22
  • 37
0

You can use pyinstaller (to install with pip: pip install pyintaller see project page) to create a single executable file and place the config file in the same folder. be able to work with the app.exe.config files on a per project basis.

pyinstaller --onefile script.py

this will create a dist folder inside your current working directory with an exe file (script.exe) and there you can place your script.exe.config file which will parse upon running script.exe

gsmari
  • 17
  • 3