2013-04-04 63 views
2

我試圖製作一個程序,使用位於(引用).dll中的自定義組件,從內存中運行程序(通過Assembly.Load(bin),如here所述)。如何將包含在dll中的組件嵌入到exe中,以便它可以從內存中運行?

由於運行內存代碼運行.exe,組件如何嵌入到.exe中以便不需要.dll?

我試過ILMerge,但生成的.exe不會從內存中運行。 我看了this,但我不認爲它的工作原理,如果你引用的.dll文件(我不得不因爲它包含的窗體上的組件)

更新

讀過NSGaga的答案,我試過如下:

  • 設置的組件.dll文件包含在項目中是一個嵌入的資源
  • 作了除了Program.cs

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Reflection; 
    using System.Windows.Forms; 
    
    namespace MyApp 
    { 
        static class Program 
        { 
         /// <summary> 
         /// The main entry point for the application. 
         /// </summary> 
         [STAThread] 
         static void Main() 
         {    
          AppDomain.CurrentDomain.AssemblyResolve += 
          (sender, args) => 
          { 
           // System.Diagnostics.Debugger.Break(); 
           String resourceName = "MyApp." + 
    
            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); 
    
           } 
    
          }; 
          Application.EnableVisualStyles(); 
          Application.SetCompatibleTextRenderingDefault(false); 
          Application.Run(new MainForm()); 
         } 
        } 
    } 
    

不幸的是,這並不工作,我得到一個FileNotFoundException

無法加載文件或程序集 'MetroFramework,版本= 1.2.0.0,文化=中性公鑰= 5f91a84759bf584a'或其依賴之一。該系統找不到指定的文件。

Application.Run(new MainForm());行發生異常。此外,突破/添加消息框等,我不相信AssemblyResolve處理程序被稱爲 - 我做錯了什麼?

+0

其實我認爲你最後談論的方法是可行的:當CLR搜索一個dll時,它不僅在一個地方查找它,並且'AssemblyResolve'事件也會被觸發,所以你會發現你的DLL。你在項目中引用了dll並不重要。只是嘗試刪除您的調試文件夾的物理DLL,看看會發生什麼 – ppetrov 2013-04-04 22:01:04

+0

我編輯過你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 – 2013-04-05 00:49:40

+0

是不能將嵌入式程序集寫出到存儲設備的要求之一? – 2013-04-06 14:54:04

回答

1

你已經回答了很多 - 來自Jeffrey Richter的manual solution應該工作得很好 - ILMerge有問題(例如WPF)。

那是因爲我打得瓦特/一個很長一段時間,但是這是rougly你需要做什麼......

1)準備好您的應用程序了一下 - 這意味着 - 你無法加載任何東西,直到您設置您的AssemblyResolve處理程序。這也意味着任何例如從'主'(甚至之後)調用將不得不被'解決'之前。簡而言之,將您需要的所有內容「移動」到「稍後」的代碼中,

2)儘快添加處理程序。我只會重複一下Richter的代碼w /一些信息。也看看http://support.microsoft.com/kb/319292

AppDomain.CurrentDomain.AssemblyResolve += 
(sender, args) => 
{ 
    // System.Diagnostics.Debugger.Break(); 
    // Lookup what's your namespace in project properties 
    String resourceName = "YourAssemblyNamespace." + 
     new AssemblyName(args.Name).Name + ".dll"; 
    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 
    { 
==> 
     if (stream == null) 
      return null; 
==> 
     Byte[] assemblyData = new Byte[stream.Length]; 
     stream.Read(assemblyData, 0, assemblyData.Length); 
     return Assembly.Load(assemblyData); 
    } 
}; 

3)進行測試 - 將你的「負荷」 LIB代碼上的一些「咔嗒」或東西 - 並把一個「休息」(像我一樣),

4)添加您的DLL -s`作爲嵌入式資源' - 即就像bmp或其他東西一樣,在根中。添加外部文件 - 然後將其設置爲屬性爲「嵌入式資源」。

5)構建應用程序 - 並注意大小的變化,應該是相當多的DLL-S的區別,

6)去你的bin目錄 - 和刪除DLL-S。不要再建項目,並從VS /調試搬走,

7)啓動應用程序,並觀察...

注: 你可能會得到異常(如你的lib建議) - 你需要處理,如果流== null。 '問題'是各種dll經常'試圖加載(或從應用程序請求),並且它們安全失敗 - 因爲我們添加了'處理程序',我們負責以同樣的方式輕度失敗。請參閱上面編輯的代碼。

您的代碼編輯:

您可能需要移動開始了一下後點窗口 - 你檢查該處理程序被調用(斷點和所有 - 做一些痕跡太)。

問題是MainWindow分辨率只要it gets visible開始 - 即在Main - 這發生before實際代碼運行或處理程序設置。所以......

static void Main(){ 
    ... 
    DoAppSetup(); 
    // Application.EnableVisualStyles(); 
    // Application.SetCompatibleTextRenderingDefault(false); 
    // Application.Run(new MainForm()); 
} 
static void DoAppSetup(){ 
Application.EnableVisualStyles(); 
Application.SetCompatibleTextRenderingDefault(false); 
Application.Run(new MainForm()); 
} 

...這樣,你的處理程序應該甚至建立了一個任何事情之前嘗試解決。

+0

有趣的是,我非常想使用Richter的解決方案 - 我已經與你的建議一起去了,但是沒有運氣 - 請看這個問題的更新。 – James 2013-04-06 14:25:38

+0

我放了一個編輯 - 應該做的伎倆。而且你必須稍微處理一下 - 我不可能爲你的特定解決方案進行調試。這是有效的,之前已經過測試和測試 - 而且我只做了一個快速檢查,所有的工作都很好。但是,您的代碼可能需要不同的東西。我給你的指導方針,你做其餘的:)。至於Richter的代碼 - 那裏的數量比我在這裏給你的要少得多,這是一個有你需要的所有信息 - 即最好的你可以得到IMO :)的解決方案。 – NSGaga 2013-04-06 14:41:00

+0

+1 Fantastic;非常感謝你 - 這是一種享受。它創建了'DoAppSetup()'函數,可以在正確的時間調用處理函數。 – James 2013-04-06 16:13:08

0

如果您直接訪問嵌入式資源,那麼只需將它們嵌入到EXE中,如果它們位於第三方DLL中,那麼您將無法將它們取出並嵌入到實際中和潛在的法律問題。

如果可以的話,我建議直接嵌入到EXE中。

+0

對,謝謝你的建議。 – James 2013-04-05 12:33:55

相關問題