2008-10-09 65 views
449

Bạn biết đấy, tôi chưa thấy câu trả lời hay cho việc này ở bất kỳ đâu. Có thể nhúng một DLL đã tồn tại trước vào một tệp C# đượ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 được?Nhúng các tệp DLL vào một tệp thực thi được biên dịch

Thông thường, tôi rất tuyệt khi chỉ để các tệp 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ành thật không biết.

+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). –

+1

@ PawełDyda: Bạn có thể nhúng dữ liệu nhị phân thô vào một hình ảnh PE (xem [RCDATA] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa381039.aspx)). Không cần chuyển đổi (hoặc được khuyến nghị). – IInspectable

Trả lời

559

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

Install-Package Costura.Fody 

Sau khi thêm nó vào dự án này, nó sẽ tự động nhúng tất cả các tài liệu tham khảo được sao chép vào thư mục đầu ra vào lắp ráp chính của bạn. Bạn có thể muốn để làm sạch các tập tin nhúng bằng cách thêm một mục tiêu của dự án:

Install-CleanReferencesTarget 

Bạn cũng sẽ có thể tùy chọn Include của pdb, loại trừ hội nhất định, hoặc trích xuất các hội đồng một cách nhanh chóng. Theo như 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 nay, một số người đang cố gắng để thêm support for DNX.

+54

Cảm ơn bạn đã gợi ý 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 assembly theo mặc định. – Daniel

+7

Ghét là một 'tôi quá', nhưng tôi cũng vậy - điều này đã cứu tôi rất nhiều đ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 đơn và bây giờ nhỏ hơn exe gốc và dll đã được kết hợp ... Tôi chỉ sử dụng nó trong vài ngày, vì vậy tôi không thể nói rằng tôi ' đã đặt nó thông qua các bước của nó, nhưng chặn bất cứ điều gì xấu popping lê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 tôi. Nó chỉ hoạt động! – mattezell

+11

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

6

Bạn có thể thêm các tệp DLL dưới dạng tài nguyên được nhúng, 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 đã có) chưa. Tuy nhiên,

Các tệp thiết lập rất dễ thực hiện, vì tôi không nghĩ rằng điều này sẽ đáng giá.

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

+0

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

71

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

Xem thêm:How can a C++ windows dll be merged into a C# application exe?

+0

Tôi quan tâm đến việc hợp nhất DLL Gốc, có bất kỳ tài liệu nào không ? –

+4

Xem thêm: http://stackoverflow.com/questions/108971/using-side-by-side-assemblies-to-load-the-x64-or-x32-version-of-a-dll/156024#156024 –

0

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

Trừ khi bạn có 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 xem xét việc chuyển sang C++/CLI.

5

Một sản phẩm có thể xử lý này tao nhã là smartassembly, tại SmartAssembly.com. Sản phẩm này, ngoài việc sáp nhập tất cả các phụ thuộc vào một DLL duy nhất, (tùy chọn) làm xáo trộn mã của bạn, loại bỏ siêu dữ liệu bổ sung để giảm kích thước tệp kết quả và cũng có thể thực sự 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 xử lý/báo cáo ngoại lệ toàn cầu mà nó thêm vào phần mềm của bạn (nếu muốn) mà tôi không dành thời gian để hiểu, nhưng có thể hữu ích. Tôi tin rằng nó cũng có một API dòng lệnh để bạn có thể làm cho nó trở thành một phần của quá trình xây dựng của bạn.

6

Kiểm tra boxedapp

Nó có thể nhúng một dll vào bất kỳ ứng dụng nào. Bằng văn bản trong C# quá, tất nhiên :)

Hy vọng điều đó sẽ hữu ích.

+3

Cảm ơn. Điều này giúp tôi gói tất cả tham chiếu và ứng dụng của tôi thực thi thành một phần. Cảm ơn một lần nữa. –

+1

Tôi cũng sử dụng boxedapp. Tôi nghĩ rằng nó sẽ giúp bạn. –

+0

SDK mạnh mẽ để ảo hóa. Giải pháp tuyệt vời. – MastAvalons

0

Nói chung, bạn sẽ cần một số hình thức công cụ xây dựng bài đăng để thực hiện quá trình hợp nhất như bạn mô tả. Có một công cụ miễn phí được gọi là Eazfuscator (eazfuscator.blogspot.com/) được thiết kế cho mangling bytecode cũng xử lý việc hợp nhất assembly. Bạn có thể thêm điều này vào một dòng lệnh xây dựng bài viết với Visual Studio để hợp nhất các hội đồng của bạn, nhưng mileage 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 trival.Bạn cũng có thể kiểm tra xem liệu xây dựng có làm cho NANT không hoạt động có khả năng hợp nhất các hội đồng sau khi xây dựng, nhưng tôi không đủ quen thuộc với NANT để nói liệu chức năng có được xây dựng hay không.

Ngoài ra còn có rất 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.

Hoặc nếu bạn không cần điều này được thực hiện tự động, có một số công cụ như ILMerge sẽ hợp nhất các hội đồng .net vào một tệp duy nhất.

Vấn đề lớn nhất 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 nói chung là với các tệp dll NUnit).

+1

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

+0

+1 Bobby. Tôi nên nhớ điều đó. Về tất cả các Eazfucator không cho bạn là trừu tượng các cuộc gọi thực tế để ILMerge với một tập tin cấu hình tổng quát hơn. – wllmsaccnt

24

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 hội đồng .NET vào một assembly.
  • Mono mkbundle, đóng gói exe và tất cả các hội đồng với libmono vào một gói nhị phân duy nhất.
  • IL-Repack là một thay đổi FLOSS đối với 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à làm cho kết quả nhỏ hơn.

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

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

+0

NETZ dường như biến mất – Rbjz

+0

Wow - Tôi nghĩ cuối cùng tôi đã tìm thấy nó, sau đó tôi đọc nhận xét này. Dường như nó đã biến mất hoàn toàn. Có dĩa không? – Mafii

+0

Vâng, nó chỉ chuyển sang GitHub và nó không còn được liên kết trên trang web ... vì vậy "biến mất hoàn toàn" 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 liên kết. – Bobby

66

Chỉ cần kích chuột phải vào dự án của bạn trong Visual Studio, chọn Project Properties -> Tài nguyên -> Add Resource -> Add File ... hiện Và bao gồm mã dưới đây để App.xaml.cs hoặc tương đương của bạn.

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); 
} 

Dưới đây là gốc bài viết trên blog của tôi: http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

+4

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 http://stackoverflow.com/a/20306095/568266 – Matthias

+3

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

+3

Hai ý kiến ​​về điều này. Một: bạn nên kiểm tra nếu 'byte' là null, và nếu có, trả về null ở đó. Có thể dll là _not_ trong tài nguyên, sau khi tất cả. Hai: Điều này chỉ hoạt động nếu chính lớp đó không có "sử dụng" cho bất kỳ thứ gì từ assembly đó. Đố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 của mình sang một tệp mới và tạo một chương trình chính mới nhỏ mà chỉ thực hiện điều này và sau đó gọi chính ban đầu trong lớp cũ. – Nyerguds

16

ILMerge có thể kết hợp lắp ráp với một hội duy nhất cung cấp lắp ráp đã chỉ mã số 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ũng có cả .Netz cả hai đều miễn phí. Ứng dụng phải trả phí bao gồm BoxedAppSmartAssembly.

Nếu bạn phải hợp nhất các hội đồng với mã không được quản lý, tôi sẽ đề xuất SmartAssembly. Tôi chưa bao giờ bị trục trặc với SmartAssembly nhưng với tất cả những người khác. Ở đây, nó có thể nhúng các phụ thuộc bắt buộc làm tài nguyên cho exe chính của bạn.

Bạn có thể làm tất cả điều này theo cách thủ công 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 AppDomain's Assembly 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à 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 byte vào tệp và tải từ vị trí của tệp. Để tránh vấn đề về gà và trứng, bạn phải đảm bảo bạn khai báo trình xử lý trước khi truy cập assembly 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 kỳ thứ gì phải xử lý assembly) bên trong phần tải (lắp ráp giải quyết). Ngoài ra hãy cẩn thận để đảm bảo GetMyApplicationSpecificPath() không phải là thư mục tạm thời 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 của chính bạn (không phải là nó sẽ bị xóa trong khi chương trình của bạn truy cập vào dll, nhưng ít nhất là phiền toái của nó. vị trí tốt). Cũng lưu ý rằng bạn phải viết các byte mỗi lần, bạn không thể tải từ vị trí chỉ 'cos dll đã nằm ở đó.

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

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ể nhìn thấy link này hoặc this như thế nào để tải dlls như vậy.

+0

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

+0

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

+1

EAZfuscator bây giờ là thương mại. – Telemat

3

Bên cạnh ILMerge, nếu bạn không muốn bận tâm đến công tắc dòng lệnh, tôi thực sự khuyên bạn nên ILMerge-Gui. Đó là một dự án mã nguồn mở, thực sự tốt!

6

Không có cách tiếp cận ILMerge cũng như việc xử lý sự kiện AssemblyResolve của Lars Holm Jensen sẽ hoạt động đối với một máy chủ lưu trữ plugin. Nói thực thi H tải lắp ráp P động và truy cập thông qua giao diện IP được xác định trong một hội đồng riêng biệt. Để nhúng IP vào H một trách nhiệm cần một thay đổi nhỏ để mã Lars của:

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; 
}; 

Bí quyết để xử lý nỗ lực lặp đi lặp lại để giải quyết cùng một assembly và trả lại một hiện tại thay vì tạo ra một trường hợp mới.

CHỈNH SỬA: Cho phép nó hỏng. Serialization, đảm bảo trả về null cho tất cả các cụm không được nhúng trong máy của bạn, do đó làm mặc định hành vi chuẩn. Bạn có thể nhận danh sách các thư viện này theo:

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ả lại null nếu hội đồng được thông qua không thuộc về IncludedAssemblies.

+0

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

11

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

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 nó một chút, đã làm công việc, tnx buddy! –

+0

Dự án https://libz.codeplex.com/ sử dụng quy trình này nhưng nó cũng sẽ thực hiện một số việc khác 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ý] (https: // mef.codeplex.com/wikipage?title=Using%20Catalogs) "(mà tự nó quá trình này sẽ phá vỡ) –

2

Nghe có vẻ đơn giản, nhưng WinRar cung cấp tùy chọn để nén một loạt tệp thành tệp thực thi tự giải 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 thành đường dẫn, tệp để thực thi sau khi trích xuất, biểu trưng/văn bản tùy chỉnh cho cửa sổ bật lên được hiển thị trong quá trình trích xuất, không có cửa sổ bật lên, văn bản thỏa thuận giấy phép, v.v.
Có thể hữu ích trong một số trường hợp.

+0

Windows chính nó có một công cụ tương tự được gọi là iexpress. [Đây là hướng dẫn] (http://www.instructables.com/id/Create-A-Self-Extracting-Archive/) –

10

Để mở rộng trên @Bobby's asnwer ở 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 vào một hội đồng khi bạn xây dựng.

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

Đây là một mẫu đơn giản mà kết hợp ExampleAssemblyToMerge.dll vào sản lượng 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

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

Trong kịch bản xyz.cs của bạn, thêm những dòng sau đây sau khi các chỉ thị (ví dụ của tôi là dành 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" 

Tỉ, res và thẻ ico sẽ được chọn của các .vbs script dưới đây để tạo lệnh csc.

Sau đó thêm người gọi lắp ráp phân giải trong chính:

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

... và thêm phân giải bản thân ở đâu đó trong lớp:

 
    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     String resourceName = new AssemblyName(args.Name).Name + ".dll"; 

     using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 
     { 
      Byte[] assemblyData = new Byte[stream.Length]; 
      stream.Read(assemblyData, 0, assemblyData.Length); 
      return Assembly.Load(assemblyData); 
     } 

    } 

Tôi đặt tên cho kịch bản vbs để phù hợp với. cs filename (ví dụ ssh.vbs tìm kiếm ssh.cs); điều này làm cho chạy kịch bản nhiều lần dễ dàng hơn nhiều, nhưng nếu bạn không phải là một thằng ngốc như tôi thì một kịch bản chung có thể lấy mục tiêu.cs tập tin từ một drag-and-drop:

 
    Dim name_,oShell,fso 
    Set oShell = CreateObject("Shell.Application") 
    Set fso = CreateObject("Scripting.fileSystemObject") 

    'TAKE THE VBS SCRIPT NAME AS THE TARGET FILE NAME 
    '################################################ 
    name_ = Split(wscript.ScriptName, ".")(0) 

    'GET THE EXTERNAL DLL's AND ICON NAMES FROM THE .CS FILE 
    '####################################################### 
    Const OPEN_FILE_FOR_READING = 1 
    Set objInputFile = fso.OpenTextFile(name_ & ".cs", 1) 

    'READ EVERYTHING INTO AN ARRAY 
    '############################# 
    inputData = Split(objInputFile.ReadAll, vbNewline) 

    For each strData In inputData 

     if left(strData,7)="//+ref>" then 
      csc_references = csc_references & " /reference:" &   trim(replace(strData,"//+ref>","")) & " " 
     end if 

     if left(strData,7)="//+res>" then 
      csc_resources = csc_resources & " /resource:" & trim(replace(strData,"//+res>","")) & " " 
     end if 

     if left(strData,7)="//+ico>" then 
      csc_icon = " /win32icon:" & trim(replace(strData,"//+ico>","")) & " " 
     end if 
    Next 

    objInputFile.Close 


    'COMPILE THE FILE 
    '################ 
    oShell.ShellExecute "c:\windows\microsoft.net\framework\v3.5\csc.exe", "/warn:1 /target:exe " & csc_references & csc_resources & csc_icon & " " & name_ & ".cs", "", "runas", 2 


    WScript.Quit(0) 
Các vấn đề liên quan