[英]Loading C# DLL in Delphi does not find dependent library DLL
我用C#編寫了一個小互操作DLL,供Delphi(非COM)使用。
我正在使用iTextSharp
生成PDF文件。
C#DLL基本上非常簡單:
namespace ClassLibrary1
{
public class Class1
{
[DllExport("Test1", CallingConvention = CallingConvention.StdCall)]
public static void Test1()
{
System.IO.FileStream fs = new FileStream(@"D:\x.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
Document document = new Document();
document.SetPageSize(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
document.Add(new Paragraph("Hello World"));
document.Close();
writer.Close();
fs.Close();
}
}
}
而Delphi托管應用程序代碼(位於其他文件夾中):
procedure TForm1.Button1Click(Sender: TObject);
type
TDLLProc = procedure; stdcall;
var
DLLModule: HMODULE;
DLLProc: TDLLProc;
begin
// SetCurrentDir('G:\Projects\Test\ClassLibrary1\bin\x86\Release');
DLLModule := LoadLibrary('G:\Projects\Test\ClassLibrary1\bin\x86\Release\ClassLibrary1.dll');
if DLLModule = 0 then RaiseLastWin32Error;
DLLProc := GetProcAddress(DLLModule, 'Test1');
if @DLLProc = nil then RaiseLastWin32Error;
DLLProc(); // external exception E0434352
end;
問題在於,調用該方法會引發external exception E0434352
因為由於某些原因,C#DLL無法找到itextsharp.dll
。
如果我將itextsharp.dll
復制到Project1.exe
目錄,則一切正常。
如果我將Project1.exe
復制到'G:\\Projects\\Test\\ClassLibrary1\\bin\\x86\\Release\\
一切正常。
我不希望將ClassLibrary1.dll
和itextsharp.dll
放在我的EXE程序目錄中,而是從它們自己的目錄中使用它們。
我嘗試過顯式設置SetCurrentDirecory
,也嘗試過SetDllDirectory
,也嘗試過LoadLibraryEx
。 沒有任何幫助。
似乎即使將itextsharp.dll
DLL(僅用於測試)放在C:\\Windows
目錄中,我也遇到同樣的異常!
我該怎么做才能解決這個問題?
編輯:如果要使用System.Reflection.Assembly.LoadFrom
來加載itextsharp.dll並訪問其每個文件,請查看@Peter Wolf在注釋中建議的從單獨的文件夾中加載.NET itextsharp.dll
集。通過反射的類/方法/成員/等。 即
[DllExport("Test1", CallingConvention = CallingConvention.StdCall)]
public static void Test1()
{
var asm = System.Reflection.Assembly.LoadFrom(@"G:\Projects\Test\ClassLibrary1\bin\x86\Release\itextsharp.dll");
Type tDocument = asm.GetType("iTextSharp.text.Document", true, true);
dynamic document = Activator.CreateInstance(tDocument);
Type tPageSize = asm.GetType("iTextSharp.text.PageSize", true, true);
tPageSize.GetMethod("GetRectangle");
// ETC... ETC... ETC...
}
這實際上有效,但是對我來說這看起來很瘋狂! 僅僅為了做到這一點,就破壞一個非常簡單且良好的C#代碼。
我只是不敢相信沒有一種正常的方式來加載與宿主Delphi應用程序不同的文件夾中的C#DLL。
有沒有一種本能/正常和直接的方法來做到這一點而無需反思????
您可以通過AssemblyResolve
事件連接到C#DLL中的程序集解析機制。 在這里,您將有機會找到並加載.NET運行時無法單獨定位的程序集。 您可以在類構造函數中安裝處理程序(在您的情況下為Class1
),但是如果您的DLL在Class1
之外具有某些入口點,那么這可能還不夠。 安裝處理程序的代碼是:
using System;
using System.IO;
using System.Linq;
using System.Reflection;
publi class Class1
{
static Class1()
{
var dllDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name);
if (assembly != null)
{
return assembly;
}
var fileName = args.Name.Split(',')[0] + ".dll";
var filePath = Path.Combine(dllDirectory, fileName);
if (File.Exists(filePath))
{
return Assembly.LoadFile(filePath);
}
return null;
};
}
// ...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.