it-swarm-vi.tech

Làm thế nào một dll windows C++ có thể được hợp nhất vào exe ứng dụng C #?

Tôi có một chương trình Windows C # sử dụng dll C++ cho dữ liệu i/o. Mục tiêu của tôi là triển khai ứng dụng dưới dạng EXE duy nhất.

Các bước để tạo ra một thực thi như vậy là gì?

32
Noah

Triển khai lắp ráp đơn mã được quản lý và không được quản lý [.__.] Chủ nhật, ngày 4 tháng 2 năm 2007

Các nhà phát triển .NET thích triển khai XCOPY. Và họ yêu các thành phần hội duy nhất. Ít nhất tôi luôn cảm thấy khó chịu, nếu tôi phải sử dụng một số thành phần và cần nhớ một danh sách các tệp cũng bao gồm với hội chính của thành phần đó. Vì vậy, khi gần đây tôi phải phát triển một thành phần mã được quản lý và phải gia tăng nó bằng một số mã không được quản lý từ C DLL (thx cho Marcus Heege vì đã giúp tôi điều này!), Tôi đã nghĩ về cách tạo ra nó dễ dàng hơn để triển khai hai DLL. Nếu đây chỉ là hai tập hợp, tôi có thể đã sử dụng ILmerge để đóng gói chúng chỉ trong một tệp. Nhưng điều này không làm việc cho các thành phần mã hỗn hợp với các DLL được quản lý cũng như không được quản lý.

Vì vậy, đây là những gì tôi nghĩ ra cho một giải pháp:

Tôi bao gồm bất kỳ tệp DLL nào tôi muốn triển khai với Hội đồng chính thành phần của tôi như là tài nguyên được nhúng. [.___ Sau đó, tôi thiết lập một trình xây dựng lớp để trích xuất các tệp DLL như bên dưới. Lớp ctor được gọi chỉ một lần trong mỗi AppDomain, vì vậy, nó là một chi phí không thể bỏ qua, tôi nghĩ vậy.

namespace MyLib
{
    public class MyClass
    {
        static MyClass()
        {
            ResourceExtractor.ExtractResourceToFile("MyLib.ManagedService.dll", "managedservice.dll");
            ResourceExtractor.ExtractResourceToFile("MyLib.UnmanagedService.dll", "unmanagedservice.dll");
        }

        ...

Trong ví dụ này tôi đã bao gồm hai DLL làm tài nguyên, một là DLL mã không được quản lý và một là mã được quản lý DLL (chỉ nhằm mục đích trình diễn), để chỉ ra cách thức kỹ thuật này hoạt động cho cả hai loại mã.

Mã để trích xuất các DLL thành các tệp của riêng họ rất đơn giản:

public static class ResourceExtractor
{
    public static void ExtractResourceToFile(string resourceName, string filename)
    {
        if (!System.IO.File.Exists(filename))
            using (System.IO.Stream s = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
                {
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, b.Length);
                    fs.Write(b, 0, b.Length);
                }
    }
}

Làm việc với một hội đồng mã được quản lý như thế này giống như bình thường - gần như vậy. Bạn tham chiếu nó (ở đây: ManagedService.dll) trong dự án chính thành phần của bạn (ở đây: MyLib), nhưng đặt thuộc tính Copy Local thành false. Ngoài ra, bạn liên kết trong Hội đồng dưới dạng Mục hiện có và đặt Hành động xây dựng thành Tài nguyên nhúng.

Đối với mã không được quản lý (ở đây: UnmanagedService.dll), bạn chỉ cần liên kết trong DLL dưới dạng Mục hiện có và đặt Hành động xây dựng thành Tài nguyên nhúng. Để truy cập các chức năng của nó, hãy sử dụng thuộc tính DLLImport như bình thường, ví dụ:.

[DllImport("unmanagedservice.dll")] public extern static int Add(int a, int b);

Đó là nó! Ngay khi bạn tạo phiên bản đầu tiên của lớp với ctor tĩnh, các DLL được nhúng sẽ được trích xuất thành các tệp của riêng chúng và sẵn sàng sử dụng như thể bạn triển khai chúng dưới dạng các tệp riêng biệt. Miễn là bạn có quyền ghi cho thư mục thực thi, điều này sẽ hoạt động tốt cho bạn. Ít nhất là đối với mã nguyên mẫu Tôi nghĩ rằng cách triển khai lắp ráp đơn này khá thuận tiện.

Thưởng thức!

http://weblogs.asp.net/ralfw/archive/2007/02/04/single-Assugging-deployment-of-managed-and-unmanaged-code.aspx

16
Nick

Hãy thử boxedapp ; nó cho phép tải tất cả các DLL từ bộ nhớ. Ngoài ra, có vẻ như bạn thậm chí có thể nhúng thời gian chạy .net. Tốt để tạo một ứng dụng thực sự độc lập ...

3
Art

Chỉ cần nhấp chuột phải vào dự án của bạn trong Visual Studio, chọn Thuộc tính dự án -> Tài nguyên -> Thêm tài nguyên -> Thêm tệp hiện có [.__.] Và bao gồm mã bên dưới vào App.xaml.cs hoặc tương đương.

public App()
{
    AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(',') ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");

    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;

    System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

    byte[] bytes = (byte[])rm.GetObject(dllName);

    return System.Reflection.Assembly.Load(bytes);
}

Đây là bài viết trên blog ban đầu của tôi: [.__.] http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-Assugging/

1
Lars Holm Jensen

Sử dụng Fody.Costura nuget

  1. Mở giải pháp của bạn -> Dự án -> Quản lý gói Nuget
  2. Tìm kiếm Fody.Costura
  3. Biên dịch your dự án

Đó là nó !

Nguồn: [.__.] Http://www.manuelmeyer.net/2016/01/net-power-tip-10-merging-assemblies/

1
automan

Bạn đã thử ILMerge chưa? http://research.Microsoft.com/~mbarnett/ILMerge.aspx

ILMerge là một tiện ích có thể được sử dụng để hợp nhất nhiều cụm .NET thành một hội duy nhất. Nó được cung cấp miễn phí để sử dụng từ trang Công cụ & Tiện ích tại Trung tâm nhà phát triển Microsoft .NET Framework. 

Nếu bạn đang xây dựng C++ DLL với cờ /clr (tất cả hoặc một phần C++/CLI), thì nó sẽ hoạt động:

ilmerge /out:Composite.exe MyMainApp.exe Utility.dll

Tuy nhiên, nó sẽ không hoạt động với Windows (bản địa) thông thường DLL. 

1
Raithlin

Hội thông minh có thể làm điều này và hơn thế nữa. Nếu dll của bạn có mã không được quản lý, nó sẽ không cho phép bạn hợp nhất các dll với một hội duy nhất, thay vào đó nó có thể nhúng các phụ thuộc cần thiết làm tài nguyên cho exe chính của bạn. Mặt trái của nó, nó không miễn phí.

Bạn có thể thực hiện việc này một cách thủ công bằng cách nhúng dll vào tài nguyên của mình và sau đó dựa vào Hội đồng của AppDomain ResolveHandler. Khi nói đến các dll chế độ hỗn hợp, tôi đã tìm thấy nhiều biến thể và hương vị của cách tiếp cận ResolveHandler không hoạt động đối với tôi (tất cả đều đọc dll byte vào bộ nhớ và đọc từ nó). Họ đều làm việc cho các dlls được quản lý. Đây là những gì làm việc cho tôi:

static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
    {
        string assemblyName = new AssemblyName(args.Name).Name;
        if (assemblyName.EndsWith(".resources"))
            return null;

        string dllName = assemblyName + ".dll";
        string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);

        using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
        {
            byte[] data = new byte[stream.Length];
            s.Read(data, 0, data.Length);

            //or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);

            File.WriteAllBytes(dllFullPath, data);
        }

        return Assembly.LoadFrom(dllFullPath);
    };
}

Chìa khóa ở đây là ghi các byte vào một tệp và tải từ vị trí của nó. Để tránh sự cố gà và trứng, bạn phải đảm bảo rằng bạn khai báo trình xử lý trước khi truy cập vào hội và rằng bạn không truy cập vào các thành viên hội (hoặc khởi tạo bất cứ điều gì phải giải quyết với hội) trong phần nạp (giải quyết hội). Ngoài ra, hãy cẩn thận để đảm bảo GetMyApplicationSpecificPath() không phải là bất kỳ thư mục tạm thời nào vì các tệp tạm thời có thể bị xóa bởi các chương trình khác hoặc bởi chính bạn (không phải nó sẽ bị xóa trong khi chương trình của bạn đang truy cập dll, nhưng ít nhất nó gây phiền toái vị trí tốt). Cũng lưu ý rằng bạn phải ghi các byte mỗi lần, bạn không thể tải từ vị trí chỉ vì 'dll đã ở đó.

Nếu hội hoàn toàn không được quản lý, bạn có thể thấy liên kết này hoặc này như cách tải các dll đó.

0
nawfal

Thinstall là một giải pháp. Đối với một ứng dụng windows gốc, tôi sẽ đề nghị nhúng DLL làm đối tượng tài nguyên nhị phân, sau đó giải nén nó trong thời gian chạy trước khi bạn cần.

0
titanae