32 или 64-разрядная DLL, загружаемая из .Управляемый сетью код

StackOverflow https://stackoverflow.com/questions/377181

  •  22-08-2019
  •  | 
  •  

Вопрос

У меня есть неуправляемая DLL ( scilexer.dll редактора кода Scintilla, используемого Scintilla.Net из Кодовый комплекс), который загружается из управляемого приложения через Scintilla.Сетевой компонент.Управляемое приложение Windows работает без проблем как в 32, так и в 64-разрядных средах, но мне нужно создать разные установки, использующие 64 или 32 scilexer.dll.

Есть ли способ распространять обе библиотеки DLL в 32 - и 64-разрядном формате, чтобы загрузчик DLL из .Net framework загружает неуправляемую DLL в 32 или 64-разрядном формате в зависимости от какой-либо опции .config или какой-то "магии имени пути"?

Это было полезно?

Решение

P/Invoke использует LoadLibrary для загрузки DLL-файлов, и если библиотека с заданным именем уже загружена, LoadLibrary вернет ее.Итак, если вы можете присвоить обеим версиям библиотеки DLL одинаковое имя, но поместить их в разные каталоги, вы можете сделать что-то подобное только один раз перед вашим первым вызовом функции из scilexer.dll, без необходимости дублировать ваши объявления extern:

    string platform = IntPtr.Size == 4 ? "x86" : "x64";
    string dll = installDir + @"\lib-" + platform + @"\scilexer.dll";
    if (LoadLibrary(dll) == IntPtr.Zero)
        throw new IOException("Unable to load " + dll + ".");

Другие советы

К сожалению, я ничего не знаю об этой конкретной DLL.Однако, когда вы выполняете P / Invoke самостоятельно и можете справиться с небольшим дублированием, можно создать по одному прокси-серверу для каждой платформы.

Например, предположим, что у вас есть следующий интерфейс, который должен быть реализован либо 32,либо 64-разрядной библиотекой DLL:

public interface ICodec {
    int Decode(IntPtr input, IntPtr output, long inputLength);
}

Вы создаете прокси-серверы:

public class CodecX86 : ICodec {
    private const string dllFileName = @"Codec.x86.dll";

    [DllImport(dllFileName)]
    static extern int decode(IntPtr input, IntPtr output, long inputLength);

    public int Decode(IntPtr input, IntPtr output, long inputLength) {
        return decode(input, output, inputLength);
    }
}

и

public class CodecX64 : ICodec {
    private const string dllFileName = @"Codec.x64.dll";

    [DllImport(dllFileName)]
    static extern int decode(IntPtr input, IntPtr output, long inputLength);

    public int Decode(IntPtr input, IntPtr output, long inputLength) {
        return decode(input, output, inputLength);
    }
}

И, наконец, создайте фабрику, которая подберет подходящую для вас:

public class CodecFactory {
    ICodec instance = null;

    public ICodec GetCodec() {
        if (instance == null) {
            if (IntPtr.Size == 4) {
                instance = new CodecX86();
            } else if (IntPtr.Size == 8) {
                instance = new CodecX64();
            } else {
                throw new NotSupportedException("Unknown platform");
            }
        }
        return instance;
    }
}

Поскольку библиотеки DLL загружаются лениво при первом вызове, это действительно работает, несмотря на то, что каждая платформа может загружать только ту версию, которая является родной для нее.Видишь эта статья для более подробного объяснения.

Лучшее, что я придумал, это следующее:

  • Распространяйте мое приложение с помощью двух библиотек DLL с именами 64 или 32
  • В основной код запуска включите следующее:
    
    File.Delete(Application.StartupPath + @"\scilexer.dll");
    {
      // Check for 64 bit and copy the proper scilexer dll
        if (IntPtr.Size == 4)
        {
          File.Copy(Application.StartupPath + @"\scilexer32.dll",
            Application.StartupPath + @"\scilexer.dll");
        }
        else
        {
          File.Copy(Application.StartupPath + @"\scilexer64.dll",
            Application.StartupPath + @"\scilexer.dll");
        }
    }

Вы можете поместить dll-файл в system32.32-разрядный в syswow64 и 64-разрядный в реальной system32.Для 32-разрядного приложения, когда они обращаются к system32, они перенаправляются на Syswow64.

Вы можете создать запись в реестре.Программный ключ имеет подраздел с именем Wow6432Node, который 32-разрядное приложение видит как программный ключ.

Вот что установщик powershell выполняет.

Неуправляемые библиотеки dll могут быть установлены в GAC параллельно со своими управляемыми аналогами. Эта статья следует объяснить, как это работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top