0

I have library - SQLiteCrypt, its two folder x86 and x64. In every folder file - System.Data.SQLite.dll

Project - AnyCPU

I can add reference only one time one dll for x86 project or for x64 project, but for me need use AnyCPU project. What can I do?

One way - get the current architecture and Assembly.LoadFrom. But if I use this method, I can't see hints and use intellisense its no good.

1 Answers1

1

If you want to load the right library according bitness of your AnyCPU program, do the following:

  • get RuntimeInformation.ProcessArchitecture for your program
  • load the right one from the two versions you have

The loader:

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.InteropServices;
using JetBrains.Annotations;

namespace Aubio.NET.Win32.Unused
{
    /// <summary>
    ///     Helper for loading a native library.
    /// </summary>
    [PublicAPI]
    public class NativeLibraryLoader : IDisposable
    {
        /// <summary>
        ///     Initializes a new instance of the <see cref="NativeLibraryLoader" /> class.
        /// </summary>
        /// <param name="path32">
        ///     Path to the 32-bit binary of the library.
        /// </param>
        /// <param name="path64">
        ///     Path to the 64-bit binary of the library.
        /// </param>
        /// <exception cref="FileNotFoundException">
        ///     <paramref name="path64" /> or <paramref name="path64" /> were not found.
        /// </exception>
        /// <exception cref="PlatformNotSupportedException">
        ///     The library could not be loaded.
        /// </exception>
        /// <exception cref="FileNotFoundException">
        ///     The platform is not supported.
        /// </exception>
        [SuppressMessage("ReSharper", "SwitchStatementMissingSomeCases")]
        public NativeLibraryLoader(string path32, string path64)
        {
            if (!File.Exists(path32))
                throw new FileNotFoundException("32-bit library not found.", path32);

            if (!File.Exists(path64))
                throw new FileNotFoundException("64-bit library not found.", path64);

            string path;

            switch (RuntimeInformation.ProcessArchitecture)
            {
                case Architecture.X86:
                    path = path32;
                    break;
                case Architecture.X64:
                    path = path64;
                    break;
                default:
                    throw new PlatformNotSupportedException();
            }

            NativeLibraryHandle handle;

            var description = RuntimeInformation.FrameworkDescription;
            if (description.StartsWith(".NET Framework"))
                handle = NativeMethods.LoadLibrary(path);
            else if (description.StartsWith(".NET Core"))
                handle = NativeMethods.LoadPackagedLibrary(path);
            else
                throw new PlatformNotSupportedException();

            if (handle.IsInvalid)
                throw new InvalidOperationException("Library could not be loaded.", new Win32Exception());

            Handle = handle;
        }

        [NotNull]
        private NativeLibraryHandle Handle { get; }

        /// <inheritdoc />
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (Handle.IsInvalid == false)
                Handle.Dispose();
        }

        /// <inheritdoc />
        ~NativeLibraryLoader()
        {
            Dispose(false);
        }
    }
}

The handle:

using System;
using System.Runtime.InteropServices;
using JetBrains.Annotations;

namespace Aubio.NET.Win32.Unused
{
    [UsedImplicitly]
    public sealed class NativeLibraryHandle : SafeHandle
    {
        private static readonly IntPtr InvalidHandleValue = IntPtr.Zero;

        public NativeLibraryHandle() : base(InvalidHandleValue, true)
        {
        }

        /// <inheritdoc />
        public override bool IsInvalid => handle == InvalidHandleValue;

        /// <inheritdoc />
        protected override bool ReleaseHandle()
        {
            return NativeMethods.FreeLibrary(handle);
        }
    }
}

The native methods class:

using System;
using System.Runtime.InteropServices;
using System.Text;
using Aubio.NET.Win32.Unused;

namespace Aubio.NET.Win32
{
    internal static class NativeMethods
    {
        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx
        /// </summary>
        /// <param name="lpLibFileName"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern NativeLibraryHandle LoadLibrary(string lpLibFileName);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/hh447159(v=vs.85).aspx
        /// </summary>
        /// <param name="lpwLibFileName"></param>
        /// <param name="reserved"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "LoadPackagedLibrary", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern NativeLibraryHandle LoadPackagedLibrary(string lpwLibFileName, uint reserved = 0);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/ms683152(v=vs.85).aspx
        /// </summary>
        /// <param name="hModule"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool FreeLibrary(IntPtr hModule);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx
        /// </summary>
        /// <param name="hModule"></param>
        /// <param name="lpProcName"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/ms683186(v=vs.85).aspx
        /// </summary>
        /// <param name="nBufferLength"></param>
        /// <param name="lpBuffer"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern uint GetDllDirectory(uint nBufferLength, [Out] StringBuilder lpBuffer);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203(v=vs.85).aspx
        /// </summary>
        /// <param name="lpPathName"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetDllDirectory(string lpPathName);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/hh310513(v=vs.85).aspx
        /// </summary>
        /// <param name="newDirectory"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern IntPtr AddDllDirectory(string newDirectory);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/hh310514(v=vs.85).aspx
        /// </summary>
        /// <param name="cookie"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool RemoveDllDirectory(IntPtr cookie);

        /// <summary>
        ///     https://msdn.microsoft.com/en-us/library/windows/desktop/hh310515(v=vs.85).aspx
        /// </summary>
        /// <param name="directoryFlags"></param>
        /// <returns></returns>
        [DllImport("kernel32", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetDefaultDllDirectories(uint directoryFlags);
    }
}

Source:

https://github.com/aybe/aubio.net/tree/develop/Aubio.NET/Win32

https://github.com/aybe/aubio.net/tree/develop/Aubio.NET/Win32/Unused

aybe
  • 15,516
  • 9
  • 57
  • 105