簡體   English   中英

在Delphi中加載C#DLL找不到依賴庫DLL

[英]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.dllitextsharp.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.

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