2015-05-29 2 views
5

Недавно я реализовал следующий код, чтобы программно построить проект/exe. В этой сборке exe я хотел сохранить кучу «реальных файлов» внутри ресурсов, как потоков.Программно загружать встроенный файл ресурсов

Вот как я буду добавлять файлы в файл ресурсов (в единственном числе), а затем вложение файла ресурсов в параметры компилятора:

 List<string> UserFiles = new List<string>(); 
     UserFiles.AddRange(Helpers.GetFilesInFolder(this.txt_Publish_Folder.Text)); 

     string folder = this.txt_Package_Location.Text; 
     folder = folder + "\\Package_" + DateTime.Now.ToLongTimeString().Replace(":", "_").Replace(".", "_"); 
     Directory.CreateDirectory(folder); 

     CompilerParameters parameters = new CompilerParameters(); 
     parameters.GenerateExecutable = true; 
     parameters.IncludeDebugInformation = true; 
     parameters.GenerateInMemory = false; 
     parameters.WarningLevel = 3; 
     parameters.CompilerOptions = "/optimize"; 
     parameters.OutputAssembly = folder + "\\Install_" + this.txt_AppName.Text + ".exe"; 
     parameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); 
     parameters.ReferencedAssemblies.Add("System.dll"); 
     parameters.ReferencedAssemblies.Add("System.Core.dll"); 
     parameters.ReferencedAssemblies.Add("System.Data.dll"); 
     parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll"); 
     parameters.ReferencedAssemblies.Add("System.Xml.dll"); 
     parameters.ReferencedAssemblies.Add("System.Xml.Linq.dll"); 

     CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp"); 
     if (codeProvider.Supports(GeneratorSupport.Resources)) 
     { 
      string temp = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); 
      //create temp file first, because we want to append to it so as to have a single resource file with multiple stream entries... 
      File.WriteAllText(temp, null); 
      for (int i = 0; i < UserFiles.Count; i++) 
      { 
       byte[] FileBytes = File.ReadAllBytes(UserFiles[i]); 

       using (FileStream stream = new FileStream(temp, FileMode.Append)) 
       { 
        using (ResourceWriter writer = new ResourceWriter(stream)) 
        { 
         writer.AddResource(Path.GetFileName(UserFiles[i]), FileBytes); 
        } 
       } 
      } 
      parameters.EmbeddedResources.Add(temp); 
     } 

     CompilerResults res = codeProvider.CompileAssemblyFromFile(parameters, @"C:\HIDDENPATH\Program.cs"); 

Это прекрасно работает, не дает никакой ошибки, и я действительно могу получить встроенный файл ресурсов в созданном Консольном приложении (тот, который указан выше как Prorgam.cs) через код ниже. Проблема я имею однако с «Загрузка» этого файла ресурсов в сборке приложения/получать свои ценности как-то ... вот код я до сих пор сделать это:

static void Main(string[] args) 
    { 
     Console.WriteLine("Checking for resources... please wait..."); 

     Assembly thisExe; 
     thisExe = Assembly.GetExecutingAssembly(); 
     List<string> resources = thisExe.GetManifestResourceNames().ToList(); 

     if(resources.Count >= 1) 
     { 
      try 
      { 
       string baseName = resources[0]; 
       ResourceManager mgr = new ResourceManager(baseName, thisExe); 
       Console.WriteLine("retrieved manager..."); 
       Console.ReadLine(); 
       ResourceSet set = mgr.GetResourceSet(Thread.CurrentThread.CurrentCulture, true, true); 
       int count = set.Cast<object>().Count(); 
       Console.WriteLine("Found [" + count.ToString() + "] embedded resources. Would you like to enumerate them?"); 
       ConsoleKeyInfo input = Console.ReadKey(); 
       if (input.Key == ConsoleKey.Y) 
       { 
        // Build the string of resources. 
        foreach (string resource in resources) 
         Console.WriteLine(resource); 
       } 

      } 
      catch (Exception ex) 
      { 
       Console.Write(ex.Message); 
       Console.ReadLine(); 
      } 
     } 

     Console.ReadLine(); 
    } 

Всякий раз, когда я запустить встроенный exe, я получаю следующий результат:

 

Checking for resources... please wait... 
retrieved manager... 

Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "tmpCC59.tmp.resources" was correctly embedded or linked into assembly "Install_testing" at compile time, or that all the satellite assemblies required are loadable and fully signed. 

Может кто-нибудь скажет мне, почему это происходит? Я пробовал все разные наборы культуры, о которых я мог думать, и до сих пор ничего не выходит. Является ли проблема связана с тем, как я «внедряюсь» или как «загружается»?

ответ

0

О, люди, так что это то, с чем я закончил, что на самом деле устранило все мои проблемы.

  1. Вместо того, чтобы добавить «Resource Записи» в единый «Resource File», я теперь добавлять каждый файл в качестве своего собственного ресурса, непосредственно из исходного файла (не знаю, почему я думал, что делаю тЕмп копия оригинала и с использованием потока была необходима, но это не так), как это:

     for (int i = 0; i < WebAppFiles.Count; i++) 
         { 
          parameters.EmbeddedResources.Add(WebAppFiles[i]); 
         } 
    
  2. Затем, когда приходит время, чтобы извлечь фактические файлы, вместо того, чтобы пытаться загрузить «набор» из одного «файл ресурсов», я просто извлекаю данные из каждого внедренного ресурса, например:

       for (int i = 0; i < resources.Count; i++) 
           { 
            Console.WriteLine("Extracting file: " + resources[i] + "..."); 
            Stream stream = thisExe.GetManifestResourceStream(resources[i]); 
            byte[] bytes = new byte[(int)stream.Length]; 
            stream.Read(bytes, 0, bytes.Length); 
            File.WriteAllBytes(dir + resources[i], bytes); 
           } 
    

Этот новый способ в основном означает, что компилятор, что «эти файлы необходимы для ехе и внедренные», поэтому при вызове «строить» команда, он на самом деле делает всю работу за вас и читает файлы в виде массивов байтов и вставляет их в исполняемый файл.

Затем, с другой стороны, вы просто сообщаете программе, что хотите сохранить встроенные ресурсы в виде файлов, используя свои собственные имена файлов.

Надеюсь, это поможет кому-то еще, кто пытается это сделать ... поскольку каждый другой пост для этого типа вопросов имел некоторые более сложные ответы, которые были либо неполными (например: как вставлять, а не извлекать) или didn ' t действительно работает.

Смежные вопросы