From 6aa919990d6f0f241e9e5584c78abb3b16ce6b25 Mon Sep 17 00:00:00 2001 From: Rolf Madsen Date: Tue, 9 Jun 2026 13:53:49 +0200 Subject: [PATCH] Fixed loading vcredist when vcredist is not installed. (#221) Bumped git version to 3.2.2 --- .gitversion | 2 +- OpenTap.Python/SharedLib.cs | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.gitversion b/.gitversion index b440777..1aebe2b 100644 --- a/.gitversion +++ b/.gitversion @@ -3,7 +3,7 @@ # This is the version number that will be used. Prerelease numbers are calculated by # counting git commits since the last change in this value. -version = 3.2.1 +version = 3.2.2 # A version is determined to be a "beta" prerelease if it originates from the default branch # The default branch is the first branch that matches the following regular expession. diff --git a/OpenTap.Python/SharedLib.cs b/OpenTap.Python/SharedLib.cs index be72015..b9fc767 100644 --- a/OpenTap.Python/SharedLib.cs +++ b/OpenTap.Python/SharedLib.cs @@ -62,9 +62,13 @@ static void clearError() } - [DllImport("kernel32.dll")] + [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LoadLibrary(string dllToLoad); + const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); + [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); @@ -157,13 +161,37 @@ public IntPtr GetSymbol(string symbolName) return libdl.dlsym(lib, symbolName); } + private static TraceSource log = Log.CreateSource("Python"); public static SharedLib Load(string name) { clearError(); - IntPtr p = load(name); + IntPtr p; + if (IsWin32) + { + p = LoadLibrary(name); + if (p == IntPtr.Zero) + { + // if vcredist is not installed, we can usually find it right next to python dll. + // If LoadLibraryEx is used this way, it will try to load the DLL with alternative search strategy. + // this usually resolves in it finding vcredist dll right next ot the python dll and then successfully loading. + p = LoadLibraryEx(name, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH); + if (p == IntPtr.Zero) + { + int err = Marshal.GetLastWin32Error(); + var ex = new Win32Exception(err); // gives readable message + log.Error($"Unable to load {name}: {ex.Message}"); + } + } + } + else + { + p = load(name); + } + if (p == IntPtr.Zero) { checkError(); + return null; } return new SharedLib(p);