2012-05-25 138 views
4

我正在使用C#for .NET 4.0(通過Visual Studio 2010)編寫的項目上工作。有第三方工具需要使用C/C++ DLL,並且在C#中有32位應用程序和64位應用程序的示例。使用Environment.Is64BitProcess從c#應用程序動態調用32位或64位DLL

問題是,32位演示靜態鏈接到32位DLL和64位演示靜態鏈接到64位DLL。作爲一個.NET應用程序,它可以作爲客戶端PC上的32位或64位進程運行。

.NET 4.0框架提供了Environment.Is64BitProcess屬性,該屬性在應用程序作爲64位進程運行時返回true。

我想要做的是在檢查Is64BitProcess屬性後動態加載正確的DLL。然而,當我研究動態加載庫我總是能想出如下:

[DllImport("kernel32.dll")] 
public static extern IntPtr LoadLibrary(string dllToLoad); 

[DllImport("kernel32.dll")] 
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 

[DllImport("kernel32.dll")] 
public static extern bool FreeLibrary(IntPtr hModule); 

這樣看來,這些方法是專門爲32位操作系統。是否有64位等值?

只要基於Is64BitProcess檢查調用適當的方法,是否會導致靜態鏈接32位和64位庫的問題?

public class key32 
{ 
    [DllImport("KEYDLL32.DLL", CharSet = CharSet.Auto)] 
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4); 

    public static bool IsValid() 
    { 
     ... calls KFUNC() ... 
    } 
} 

public class key64 
{ 
    [DllImport("KEYDLL64.DLL", CharSet = CharSet.Auto)] 
    private static extern uint KFUNC(int arg1, int arg2, int arg3, int arg4); 

    public static bool IsValid() 
    { 
     ... calls KFUNC() ... 
    } 
} 

...

if (Environment.Is64BitProcess) 
{ 
    Key64.IsValid(); 
} 
else 
{ 
    Key32.IsValid(); 
} 

謝謝!!

回答

1

具有諷刺意味的是,在64位系統上,kernel32.dll(位於%windir%\System32\)是64位版本,而%windir%\SysWOW64\版本是32位系統。非常不幸的命名會在這裏......

無論如何,你可以做的是綁定到兩個版本,使用的路徑,因爲我聯繫他們,兩個不同的變量名稱(比如,LoadLibrarysystem32版本和LoadLibrary32對於syswow64版本)。然後在32位系統上,您可以使用LoadLibrary,如果您檢測到64位系統,則LoadLibrary將是64位版本,而LoadLibrary32將是32位版本。然而

我懷疑,這將有助於你任何,因爲我不認爲你可以動態綁定到失配位數(要補償字!)動態庫......將有助於你的第二個例子我想,在這裏你實際上得到了兩個不同的庫,每個庫都有一個庫。

4

很多方法可以做到這一點:

  • 這是一個部署問題,剛剛獲得由安裝程序複製正確的DLL,給他們相同的名稱

  • 很少有程序實際上需要64位代碼提供的海量地址空間。只需將平臺目標設置爲x86

  • 使用[DllImport]屬性的EntryPoint字段。將其設置爲「KFUNC」。並給方法不同的名稱。現在您可以根據IntPtr的值調用其中一個或另一個。大小

展示出最後的解決方案:

[DllImport("KEYDLL32.DLL", EntryPoint = "KFUNC")] 
private static extern uint KFUNC32(int arg1, int arg2, int arg3, int arg4); 

[DllImport("KEYDLL64.DLL", EntryPoint = "KFUNC")] 
private static extern uint KFUNC64(int arg1, int arg2, int arg3, int arg4); 

... 

if (IntPtr.Size == 8) KFUNC64(1, 2, 3, 4); 
else     KFUNC32(1, 2, 3, 4); 
0

而是這樣做低級的互操作我會考慮去更多的.Net路線 - 使用插件式組件來處理它。

  • 創建2個程序集鏈接到x86和x64版本的DLL(並編譯爲正確的平臺)。
  • 使此程序集公開實現相同接口的類(或使其相同的其他方式)。確保其餘的代碼可以使用任何一個庫,可能需要使用基本類型/接口的第三個程序集。
  • 在運行時加載您手動需要的程序集。確保它不會出現在搜索路徑中,以避免錯誤地自動加載一個。

請注意,你的第二種方法(基於比特度的採摘方法)應該可以正常工作。我仍然會將具有相同接口的類中的每個DLL的所有訪問包括在內,並確保只有正確的一個可以在運行時實例化。

0

將dll保存在兩個不同的目錄中並動態調用它們。

Libs64 \ ABC.dll
Libs32 \ ABC.dll

相關問題