Nhúng DLL trong một tệp thực thi được biên dịch


618

Có thể nhúng một DLL có sẵn vào một tệp thực thi C # đã biên dịch (để bạn chỉ có một tệp để phân phối) không? Nếu có thể, làm thế nào một người sẽ làm điều đó?

Thông thường, tôi rất tuyệt khi chỉ để các DLL bên ngoài và có chương trình thiết lập xử lý mọi thứ, nhưng đã có một vài người làm việc đã hỏi tôi điều này và tôi thực sự không biết.


Tôi khuyên bạn nên kiểm tra tiện ích .NETZ, cũng nén chương trình này với sơ đồ bạn chọn: http://madebits.com/netz/help.php#single
Nathan Baulch

2
Có thể, nhưng bạn sẽ kết thúc với thực thi lớn (Base64 sẽ được sử dụng để mã hóa dll của bạn).
Paweł Dyda

Ngoài ILMerge , nếu bạn không muốn làm phiền với các công tắc dòng lệnh, tôi thực sự khuyên dùng ILMerge-Gui . Đó là một dự án nguồn mở, thực sự tốt!
tyron

2
@ PawełDyda: Bạn có thể nhúng dữ liệu nhị phân thô vào hình ảnh PE (xem RCDATA ). Không cần chuyển đổi (hoặc khuyến nghị).
IInspectable

Câu trả lời:


761

Tôi thực sự khuyên bạn nên sử dụng Costura.Fody - cho đến nay là cách tốt nhất và dễ nhất để nhúng tài nguyên vào tổ hợp của bạn. Nó có sẵn dưới dạng gói NuGet.

Install-Package Costura.Fody

Sau khi thêm nó vào dự án, nó sẽ tự động nhúng tất cả các tham chiếu được sao chép vào thư mục đầu ra vào cụm chính của bạn . Bạn có thể muốn xóa các tệp nhúng bằng cách thêm mục tiêu vào dự án của mình:

Install-CleanReferencesTarget

Bạn cũng có thể chỉ định xem có bao gồm các pdb hay không, loại trừ các hội đồng nhất định hoặc trích xuất các hội đồng một cách nhanh chóng. Theo tôi biết, các hội đồng không được quản lý cũng được hỗ trợ.

Cập nhật

Hiện tại, một số người đang cố gắng thêm hỗ trợ cho DNX .

Cập nhật 2

Đối với phiên bản Fody mới nhất, bạn sẽ cần phải có MSBuild 16 (vì vậy Visual Studio 2019). Phiên bản Fody 4.2.1 sẽ thực hiện MSBuild 15. (tham khảo: Fody chỉ được hỗ trợ trên MSBuild 16 trở lên. Phiên bản hiện tại: 15 )


79
Cảm ơn bạn cho đề nghị tuyệt vời này. Cài đặt gói và bạn đã hoàn tất. Nó thậm chí còn nén các cụm theo mặc định.
Daniel

9
Ghét phải là một "tôi cũng vậy", nhưng tôi cũng vậy - điều này đã giúp tôi rất đau đầu! Cảm ơn bạn đã giới thiệu! Điều này cho phép tôi đóng gói mọi thứ tôi cần để phân phối lại thành một exe duy nhất và bây giờ nó nhỏ hơn exe và dll ban đầu được kết hợp ... Tôi chỉ mới sử dụng nó trong vài ngày, vì vậy tôi không thể nói rằng tôi Tôi đã đặt nó qua các bước đi của nó, nhưng không có gì xấu xuất hiện, tôi có thể thấy điều này trở thành một công cụ thường xuyên trong hộp công cụ của mình. Nó chỉ hoạt động!
mattezell

19
Nó tuyệt thật. Nhưng có một nhược điểm: lắp ráp được tạo trên Windows không còn tương thích nhị phân với Linux đơn sắc. Điều đó có nghĩa là, bạn không thể triển khai lắp ráp trực tiếp lên Linux mono.
Tyler Long

7
Cái này thật đáng yêu! Nếu bạn đang sử dụng vs2018, đừng quên tệp FodyWeavers.xml được đặt ở thư mục gốc của dự án.
Alan Deep

4
Để bổ sung cho nhận xét cuối cùng: thêm FodyWeavers.xml với nội dung sau vào dự án của bạn: <? Xml version = "1.0" mã hóa = "utf-8"?> <Weavers ConfirmAssugging = "true"> <Costura /> </ Thợ dệt>
HHenn

89

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 blog ban đầu của tôi: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assugging/


6
Bạn có thể có hành vi này ra khỏi hộp. Kiểm tra câu trả lời của tôi stackoverflow.com/a/20306095/568266
Matthias

4
Cũng rất quan trọng để lưu ý một nhận xét hữu ích TUYỆT VỜI trên blog của bạn từ AshRowe: nếu bạn đã cài đặt một chủ đề tùy chỉnh, nó sẽ cố gắng giải quyết hội thảo PresentationFramework.Theme bị sập và cháy! Theo đề xuất của AshRowe, bạn chỉ cần kiểm tra xem dllName có chứa PresentationFramework như vậy không: if (dllName.ToLower (). Chứa ("speechframework")) trả về null;
YasharBahman

4
Hai bình luận về điều này. Một: bạn nên kiểm tra xem có phải byteslà null không, và nếu vậy, hãy trả về null ở đó. Rốt cuộc, có thể dll không có trong tài nguyên. Hai: Điều này chỉ hoạt động nếu bản thân lớp đó không có "sử dụng" cho bất cứ thứ gì từ hội đồng đó. Đối với các công cụ dòng lệnh, tôi đã phải chuyển mã chương trình thực tế của mình sang một tệp mới và tạo một chương trình chính nhỏ mới chỉ thực hiện điều này và sau đó gọi chính ban đầu trong lớp cũ.
Nyerguds

2
Mặt trái của phương pháp này là nó không dựa vào việc cài đặt bất kỳ lib bên ngoài nào để đạt được chức năng mong muốn. Nhược điểm của phương pháp này là nó chỉ hữu ích khi nói đến các dll được quản lý - các dll interop (ít nhất là theo thử nghiệm của tôi) không kích hoạt sự kiện assemblyresolve và ngay cả khi chúng đã thực hiện Hội đồng. Tải (<byte của một số interop dll>) không đạt được hiệu quả mong muốn xuống đường. stackoverflow.com/questions/13113131/ Mạnh Chỉ là 2c của tôi về vấn đề này
XDS

3
Chỉ trong trường hợp bất kỳ ai gặp phải vấn đề của tôi: nếu .dlltên có chứa bất kỳ dấu gạch nối nào (nghĩa là twenty-two.dll), chúng cũng sẽ được thay thế bằng dấu gạch dưới (tức là twenty_two.dll). Bạn có thể thay đổi dòng mã này thành:dllName = dllName.Replace(".", "_").Replace("-", "_");
Micah Vertal

87

Nếu họ thực sự được quản lý các hội đồng, bạn có thể sử dụng ILMerge . Đối với DLL gốc, bạn sẽ có thêm một chút việc phải làm.

Xem thêm: 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 quan tâm đến việc hợp nhất DLL bản địa, có tài liệu nào không?
Baiyan Huang


@BaiyanHuang xem github.com/boxedapp/bxilmerge , ý tưởng là tạo "ILMerge" cho các DLL gốc.
Artem Razin

Các nhà phát triển VB NET như tôi không sợ điều đó C++tại liên kết. ILMerge cũng hoạt động rất dễ dàng cho VB NET. Xem tại đây https://github.com/dotnet/ILMerge . Cảm ơn @ Shog9
Biệt thự Ivan Ferrer

26

Có, có thể hợp nhất các tệp thực thi .NET với các thư viện. Có nhiều công cụ có sẵn để hoàn thành công việc:

  • 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 cụm duy nhất.
  • Mono mkbundle , gói một exe và tất cả các hội đồng với libmono thành một gói nhị phân duy nhất.
  • IL-Repack là một FLOSS thay thế cho ILMerge, với một số tính năng bổ sung.

Ngoài ra, điều này có thể được kết hợp với Mono Linker , loại bỏ mã không sử dụng và do đó làm cho lắp ráp kết quả nhỏ hơn.

Một khả năng khác là sử dụng .NETZ , nó không chỉ cho phép nén một cụm mà còn có thể đóng gói các dll thẳng vào exe. Sự khác biệt của các giải pháp được đề cập ở trên là .NETZ không hợp nhất chúng, chúng ở riêng các cụm nhưng được đóng gói thành một gói.

.NETZ là một công cụ mã nguồn mở để nén và đóng gói các tệp thực thi Microsoft .NET Framework (EXE, DLL) để làm cho chúng nhỏ hơn.


NETZ dường như không còn nữa
Rbjz

Wow - tôi nghĩ rằng cuối cùng tôi đã tìm thấy nó, sau đó tôi đọc bình luận này. Nó dường như biến mất hoàn toàn. Có dĩa nào không?
Mafii

Chà, nó mới chuyển đến GitHub và nó không còn được liên kết trên trang web nữa ... nên "hoàn toàn biến mất" là một lời nói quá. Nhiều khả năng nó không được hỗ trợ nữa, nhưng nó vẫn còn đó. Tôi đã cập nhật các liên kết.
Bobby

20

ILMerge có thể kết hợp các hội đồng thành một hội đồng duy nhất với điều kiện hội đồng chỉ có mã được quản lý. Bạn có thể sử dụng ứng dụng dòng lệnh hoặc thêm tham chiếu vào exe và hợp nhất theo chương trình. Đối với phiên bản GUI có Eazfuscator và cả .Netz đều miễn phí. Các ứng dụng trả phí bao gồm BoxedAppSmartAssugging .

Nếu bạn phải hợp nhất các cụm với mã không được quản lý, tôi sẽ đề xuất SmartAssugging . Tôi chưa bao giờ gặp trục trặc với SmartAssugging nhưng với tất cả những người khác. Ở đây, 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.

Bạn có thể thực hiện tất cả điều này một cách thủ công mà không cần phải lo lắng nếu lắp ráp được quản lý hoặc ở chế độ hỗn hợp bằng cách nhúng dll vào tài nguyên của bạn và sau đó dựa vào Hội đồng của AppDomain ResolveHandler. Đây là một giải pháp một cửa bằng cách áp dụng trường hợp xấu nhất, tức là các hội đồng với mã không được quản lý.

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 lắp ráp và bạn không truy cập vào các thành viên lắp ráp (hoặc khởi tạo bất cứ điều gì phải xử lý lắp ráp) bên trong phần tải (giải quyết lắp ráp). Ngoài ra, hãy cẩn thận để đảm bảo GetMyApplicationSpecificPath()không có 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 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 là nó gây phiền toái. AppData rất tốt. vị trí). 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 đã ở đó.

Đối với các dll được quản lý, bạn không cần phải viết byte mà tải trực tiếp từ vị trí của dll hoặc chỉ đọc các byte và tải cụm từ bộ nhớ. Thích cái này hay sao:

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

    //or just

    return Assembly.LoadFrom(dllFullPath); //if location is known.

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


Lưu ý rằng "Xây dựng hành động" của Tài nguyên cần được đặt thành "Tài nguyên được nhúng".
Mavamaarten

@Mavamaarten Không nhất thiết. Nếu nó được thêm vào Tài nguyên.resx của dự án trước, bạn không cần phải làm điều đó.
Nyerguds

2
EAZfuscator hiện là thương mại.
Telemat

16

Các đoạn trích bởi Jeffrey Richter là rất tốt. Nói tóm lại, hãy thêm thư viện dưới dạng tài nguyên được nhúng và thêm một cuộc gọi lại trước bất cứ điều gì khác. Đây là phiên bản mã (được tìm thấy trong các nhận xét trên trang của anh ấy) mà tôi đã đặt ở đầu Phương thức chính cho ứng dụng bảng điều khiển (chỉ cần đảm bảo rằng mọi cuộc gọi sử dụng thư viện đều theo phương thức khác với Chính).

AppDomain.CurrentDomain.AssemblyResolve += (sender, bargs) =>
        {
            String dllName = new AssemblyName(bargs.Name).Name + ".dll";
            var assem = Assembly.GetExecutingAssembly();
            String resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName));
            if (resourceName == null) return null; // Not found, maybe another handler will find it
            using (var stream = assem.GetManifestResourceStream(resourceName))
            {
                Byte[] assemblyData = new Byte[stream.Length];
                stream.Read(assemblyData, 0, assemblyData.Length);
                return Assembly.Load(assemblyData);
            }
        };

1
Thay đổi một chút, đã làm công việc, bạn thân tnx!
Sean Ed-Man

Dự án libz.codeplex.com sử dụng quy trình này nhưng nó sẽ thực hiện một số việc khác giống như quản lý trình xử lý sự kiện cho bạn và một số mã đặc biệt để không phá vỡ " Danh mục khung mở rộng được quản lý " (do chính quá trình này sẽ phá vỡ)
Scott Chamberlain

Thật tuyệt!! Cảm ơn @Steve
Ahmer Afzal

14

Để mở rộng trên asnwer của @ Bobby ở trên. Bạn có thể chỉnh sửa .csproj của mình để sử dụng IL-Repack để tự động đóng gói tất cả các tệp thành một cụm khi bạn xây dựng.

  1. Cài đặt gói ILRepack.MSBuild.Task của nuget với Install-Package ILRepack.MSBuild.Task
  2. Chỉnh sửa phần AfterBuild của .csproj của bạn

Đây là một mẫu đơn giản để hợp nhất exampleAssuggingToMerge.dll vào đầu ra dự án của bạn.

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>

1
Cú pháp của IL-Repack đã thay đổi, hãy kiểm tra README.md trên repo github được liên kết ( github.com/peter/ILRepack.MSBuild.Task ). Cách này là cách duy nhất phù hợp với tôi và tôi đã có thể sử dụng ký tự đại diện để khớp với tất cả các dll mà tôi muốn đưa vào.
Seabass77

8

Bạn có thể thêm các tệp DLL dưới dạng tài nguyên được nhúng và sau đó chương trình của bạn giải nén chúng vào thư mục ứng dụng khi khởi động (sau khi kiểm tra xem chúng đã ở đó chưa).

Tuy nhiên, các tệp cài đặt rất dễ thực hiện, đến nỗi tôi không nghĩ rằng nó sẽ có giá trị.

EDIT: Kỹ thuật này sẽ dễ dàng với các hội đồng .NET. Với các DLL không phải .NET, sẽ có nhiều việc hơn (bạn phải tìm ra nơi để giải nén các tệp và đăng ký chúng, v.v.).


Ở đây bạn có một bài viết tuyệt vời giải thích cách thực hiện việc này: codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource
bluish

8

Một sản phẩm khác có thể xử lý việc này một cách thanh lịch là SmartAssugging, tại SmartAssugging.com . Sản phẩm này, ngoài việc hợp nhất tất cả các phụ thuộc vào một DLL, (tùy chọn) làm xáo trộn mã của bạn, xóa dữ liệu meta bổ sung để giảm kích thước tệp kết quả và thực sự có thể tối ưu hóa IL để tăng hiệu suất thời gian chạy.

Ngoài ra còn có một số loại tính năng báo cáo / xử lý ngoại lệ toàn cầu mà nó bổ sung vào phần mềm của bạn (nếu muốn) có thể hữu ích. Tôi tin rằng nó cũng có API dòng lệnh để bạn có thể biến nó thành một phần của quá trình xây dựng của mình.


7

Cả cách tiếp cận của ILMerge lẫn Lars Holm Jensen đều không xử lý sự kiện HộiResolve sẽ hoạt động cho máy chủ plugin. Nói H thực thi tải P lắp ráp động và truy cập nó thông qua IP giao diện được xác định trong một cụm riêng biệt. Để nhúng IP vào H, người ta cần một chút sửa đổi mã của Lars:

Dictionary<string, Assembly> loaded = new Dictionary<string,Assembly>();
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{   Assembly resAssembly;
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll","");
    dllName = dllName.Replace(".", "_");
    if ( !loaded.ContainsKey( dllName ) )
    {   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);
        resAssembly = System.Reflection.Assembly.Load(bytes);
        loaded.Add(dllName, resAssembly);
    }
    else
    {   resAssembly = loaded[dllName];  }
    return resAssembly;
};  

Thủ thuật để xử lý các nỗ lực lặp đi lặp lại để giải quyết cùng một hội đồng và trả lại tập hợp hiện có thay vì tạo một thể hiện mới.

EDIT: Hãy làm hỏng nó tuần tự hóa .NET, đảm bảo trả về null cho tất cả các hội đồng không được nhúng trong của bạn, do đó mặc định là hành vi tiêu chuẩn. Bạn có thể lấy danh sách các thư viện này bằng cách:

static HashSet<string> IncludedAssemblies = new HashSet<string>();
string[] resources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
for(int i = 0; i < resources.Length; i++)
{   IncludedAssemblies.Add(resources[i]);  }

và chỉ trả về null nếu lắp ráp đã qua không thuộc về IncludedAssemblies.


Xin lỗi vì đã đăng nó dưới dạng câu trả lời thay vì bình luận. Tôi không có quyền nhận xét câu trả lời của người khác.
Ant_222

5

.NET Core 3.0 vốn hỗ trợ biên dịch thành một .exe duy nhất

Tính năng này được bật bằng cách sử dụng thuộc tính sau trong tệp dự án của bạn (.csproj):

    <PropertyGroup>
        <PublishSingleFile>true</PublishSingleFile>
    </PropertyGroup>

Điều này được thực hiện mà không có bất kỳ công cụ bên ngoài.

Xem câu trả lời của tôi cho câu hỏi này để biết thêm chi tiết.


3

Nghe có vẻ đơn giản, nhưng WinRar cung cấp tùy chọn nén một loạt các tệp để thực thi tự giải nén.
Nó có rất nhiều tùy chọn cấu hình: biểu tượng cuối cùng, trích xuất tập tin để con đường nhất định, tập tin thực thi sau khi khai thác, logo tùy chỉnh / văn bản cho cửa sổ bật lên hiển thị trong khi khai thác, không có cửa sổ popup ở tất cả, giấy phép thỏa thuận văn bản, vv
Có thể hữu ích trong một số trường hợp .


Bản thân Windows có một công cụ tương tự gọi là iexpress. Dưới đây là hướng dẫn
Biệt thự Ivan Ferrer

2

Tôi sử dụng trình biên dịch csc.exe được gọi từ tập lệnh .vbs.

Trong tập lệnh xyz.cs của bạn, hãy thêm các dòng sau sau các lệnh (ví dụ của tôi là cho Renci SSH):

using System;
using Renci;//FOR THE SSH
using System.Net;//FOR THE ADDRESS TRANSLATION
using System.Reflection;//FOR THE Assembly

//+ref>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+res>"C:\Program Files (x86)\Microsoft\ILMerge\Renci.SshNet.dll"
//+ico>"C:\Program Files (x86)\Microsoft CAPICOM 2.1.0.2 SDK\Samples\c_sharp\xmldsig\resources\Traffic.ico"

Các thẻ ref, res và ico sẽ được chọn bởi tập lệnh .vbs bên dưới để tạo thành lệnh csc.

Sau đó thêm trình gọi trình phân giải lắp ráp trong Chính:

public static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    .

... và thêm trình phân giải chính nó vào đâu đó trong lớp:

    hội tĩnh hiện tạiDomain_AssuggingResolve (người gửi đối tượng, ResolveEventArss args)
    {
        Chuỗi resourceName = new AssociationName (args.Name) .Name + "đậm";

        bằng cách sử dụng (var stream = Hội.GetExecutingAssugging (). GetManifestResourceStream (resourceName))
        {
            Byte [] assemblyData = new Byte [stream.Lipse];
            stream.Read (assemblyData, 0, assemblyData.Lipse);
            trả lại hội.Load (assemblyData);
        }

    }

Tôi đặt tên cho tập lệnh vbs để khớp với tên tệp .cs (ví dụ: ssh.vbs tìm ssh.cs); điều này làm cho việc chạy tập lệnh dễ dàng hơn rất nhiều lần, nhưng nếu bạn không phải là một kẻ ngốc như tôi thì một tập lệnh chung có thể lấy tệp .cs đích từ kéo và thả:

    Tên mờ_, oShell, fso
    Đặt oShell = CreateObject ("Shell.Application")
    Đặt fso = CreateObject ("Scripting.fileSystemObject")

    'TÊN TÊN VBS SCRIPT TÊN TÊN GỌI TARGET
    '##################################################
    name_ = Tách (wscript.ScriptName, ".") (0)

    'NHẬN TÊN DLL VÀ ICON TUYỆT VỜI TỪ FILE .CS
    '################################################### ######
    Hằng OPEN_FILE_FOR_READING = 1
    Đặt objInputFile = fso.OpenTextFile (name_ & ".cs", 1)

    'ĐỌC MỌI THỨ VÀO MỘT ARRAY
    '##############################
    inputData = Split (objInputFile.Read ALL, vbNewline)

    Đối với mỗi strData Trong inputData

        nếu còn lại (strData, 7) = "// + ref>" thì 
            csc numferences = csc numferences & "/ tham khảo:" & trim (thay thế (strData, "// + ref>", "")) & ""
        kết thúc nếu

        nếu còn lại (strData, 7) = "// + res>" thì 
            csc_resource = csc_resource & "/ resource:" & trim (thay thế (strData, "// + res>", "")) & ""
        kết thúc nếu

        nếu còn lại (strData, 7) = "// + ico>" thì 
            csc_icon = "/ win32icon:" & trim (thay thế (strData, "// + ico>", "")) & ""
        kết thúc nếu
    Kế tiếp

    objInputFile. Đóng


    'TẠO FILE
    '################
    oShell.ShellExecute "c: \ windows \ microsoft.net \ framework \ v3.5 \ csc.exe", "/ warn: 1 / target: exe" & csc numferences & csc_resource & csc_icon & "" & name_ & ".cs" , "", "Runas", 2


    WScript.Quit (0)

0

Có thể nhưng không dễ dàng gì, để tạo ra một tổ hợp gốc / được quản lý lai trong C #. Thay vào đó, bạn sử dụng C ++ sẽ dễ dàng hơn rất nhiều, vì trình biên dịch Visual C ++ có thể tạo các tập hợp lai dễ dàng như mọi thứ khác.

Trừ khi bạn có một yêu cầu nghiêm ngặt để sản xuất một tổ hợp lai, tôi đồng ý với MusiGenesis rằng điều này thực sự không đáng để làm với C #. Nếu bạn cần làm điều đó, có lẽ hãy nhìn vào việc chuyển sang C ++ / CLI thay thế.


0

Nói chung, bạn sẽ cần một số hình thức của công cụ xây dựng bài để thực hiện hợp nhất lắp ráp như bạn đang mô tả. Có một công cụ miễn phí có tên là Eazfuscator (eazfuscator.blogspot.com/) được thiết kế để xáo trộn mã byte cũng xử lý việc hợp nhất lắp ráp. Bạn có thể thêm phần này vào dòng lệnh xây dựng bài đăng với Visual Studio để hợp nhất các hội đồng của bạn, nhưng số dặm của bạn sẽ thay đổi do các vấn đề sẽ phát sinh trong bất kỳ kịch bản hợp nhất không hợp nhất nào.

Bạn cũng có thể kiểm tra xem liệu bản dựng có tạo ra tính không hợp lý NANT có khả năng hợp nhất các cụm sau khi xây dựng hay không, nhưng bản thân tôi không đủ quen thuộc với NANT để nói liệu chức năng có được tích hợp hay không.

Ngoài ra còn có nhiều plugin Visual Studio sẽ thực hiện hợp nhất lắp ráp như là một phần của việc xây dựng ứng dụng.

Ngoài ra, nếu bạn không cần thực hiện việc này một cách tự động, có một số công cụ như ILMerge sẽ hợp nhất các cụm .net thành một tệp duy nhất.

Vấn đề lớn nhất mà tôi gặp phải khi hợp nhất các hội đồng là nếu họ sử dụng bất kỳ không gian tên tương tự nào. Hoặc tệ hơn, tham khảo các phiên bản khác nhau của cùng một dll (vấn đề của tôi thường là với các tệp dll NUnit).


1
Eazfuscator sẽ chỉ gọi IlMerge, AFAIK.
Bobby

+1 Bobby. Tôi nên nhớ điều đó. Giới thiệu về tất cả Eazfucator dành cho bạn là trừu tượng các cuộc gọi thực tế đến ILMerge với tệp cấu hình chung hơn.
wllmsaccnt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.