У меня есть dll, который существует версии на 64 бита и в на 32 бита. Мой WinForm.NET настроен для "Любого ЦП", и мой босс не позволит нам иметь отдельные установки для различных версий ОС. Таким образом, я задаюсь вопросом: если я упаковываю обоих dlls в установке, то есть ли способ сделать, чтобы WinForm определил, загружают ли его 64bit/32bit и надлежащий dll.
Я нашел эту статью для определения версии. Но я не уверен, как ввести надлежащий способ определить атрибут DLLImport на методах, которые я хочу использовать. Какие-либо идеи?
Можете ли вы импортировать их обоих и решить, какой из них вызывать через .NET?
Например:
[DllImport("32bit.dll", CharSet = CharSet.Unicode, EntryPoint="CallMe")]
public static extern int CallMe32 (IntPtr hWnd, String text, String caption, uint type);
[DllImport("64bit.dll", CharSet = CharSet.Unicode, EntryPoint="CallMe")]
public static extern int CallMe64 (IntPtr hWnd, String text, String caption, uint type);
... или вы можете использовать Marshal.GetDelegateForFunctionPointer ()
для выполнения динамического P / Invoke .
... или вызовите LoadLibrary ()
с полным путем , прежде чем среда CLR попытается загрузить его за вас.
Вы можете воспользоваться функцией SetDllDirectory API, она изменяет путь поиска для неуправляемых сборок. Храните 32-разрядные библиотеки DLL в подкаталоге x86 каталога установки приложения, а 64-разрядные библиотеки DLL - в подкаталоге x64.
Запустите этот код при запуске приложения перед выполнением любого P / Invoke:
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
...
public static void SetUnmanagedDllDirectory() {
string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
path = Path.Combine(path, IntPtr.Size == 8 ? "x64 " : "x86");
if (!SetDllDirectory(path)) throw new System.ComponentModel.Win32Exception();
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool SetDllDirectory(string path);
Мое решение - создать один абстрактный класс с конкретной версией, которая загружает и обертывает мою 32-битную DLL, и отдельной реализацией, которая загружает и обертывает 64-битную DLL. Единственный фабричный метод в базовом классе может использоваться для создания экземпляра соответствующей реализации на основе IntPtr.Size
.
Хорошая вещь в этом подходе заключается в том, что остальная часть вашего кода полностью изолирована от платформы - он просто создает объект, используя метод фабрики вашего базового класса, и работает с ним. Также очень легко вызывать несколько методов в рамках рассматриваемых библиотек DLL единообразным образом, и весь ваш «собственный» код может быть легко помещен в частную реализацию.
Вы должны создать два разных частных extern
метода и создать внутренний метод, который проверяет IntPtr.Size
и называет правильную версию.