簡體   English   中英

從.Net托管代碼加載32或64位DLL

[英]32 or 64 bit DLL loading from .Net managed code

我有一個非托管DLL(Scintilla代碼編輯器的scilexer.dll,由CodePlex的Scintilla.Net使用),它是通過Scintilla.Net組件從托管應用程序加載的。 Windows托管應用程序在32位和64位環境中運行沒有問題,但我需要創建使用64或32 scilexer.dll的不同安裝。

有沒有辦法以32位和64位格式分發這兩個DLL,以便.Net框架的DLL加載器加載32或64位格式的非托管DLL,具體取決於某些.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在第一次被調用時被懶惰地加載,這實際上是有效的,盡管每個平台只能加載原生的版本。 有關更詳細的說明,請參閱此文章

我提出的最好的是以下內容:

  • 使用名為64或32的兩個DLL分發我的應用程序
  • 在主要啟動代碼中包括以下內容:
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中。 syswow64中的32位和實際system32中的64位。 對於32位應用程序,當訪問system32時,它們被重定向到Syswow64。

您可以在注冊表中創建一個條目。 軟件密鑰有一個名為Wow6432Node的子項,32位應用程序將其視為軟件密鑰。

這是powershell安裝程序的功能

非托管dll可以與其管理對應方並排安裝到GAC中。 本文應解釋它是如何工作的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM