2015-05-29 19 views
5

Ho recentemente implementato il seguente codice per creare un progetto/exe in modo programmatico. In questa exe build, volevo memorizzare un gruppo di "file reali" all'interno delle risorse, come flussi.Caricare file di risorse incorporate al livello di programmazione

Ecco come sto aggiungendo i file nel file di risorse (singolare), e poi incorporare il file di risorse nei parametri del compilatore:

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

Questa grande opera, non cede eventuali errori, e Posso effettivamente ottenere il file di risorse incorporato nell'applicazione console che ho creato (quella citata sopra come Prorgam.cs) attraverso il codice qui sotto. Il problema che sto avendo tuttavia è con questo file di risorse nel gruppo di applicazione "Loading"/ottenere i suoi valori in qualche modo ... ecco il codice che ho finora per farlo:

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

Ogni volta che corro il built exe, ottengo il seguente risultato:

 

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. 

Qualcuno può dirmi perché questo sta succedendo? ho provato tutti i diversi set di cultura a cui potevo pensare e ancora non viene fuori nulla. Il problema è legato al modo in cui sto "incorporando" o in che modo sto "caricando"?

risposta

0

Ok gente, quindi questo è quello che ho finito con, che in realtà ha risolto tutti i miei problemi.

  1. Invece di cercare di aggiungere "risorsa" le voci in un unico "File di risorse", ora sono l'aggiunta di tutti i file come la propria risorsa, direttamente dal file di origine (non so perché ho pensato fare una copia temporanea della originale e utilizzando un flusso era necessario ma non è) in questo modo:

     for (int i = 0; i < WebAppFiles.Count; i++) 
         { 
          parameters.EmbeddedResources.Add(WebAppFiles[i]); 
         } 
    
  2. Poi, quando arriva il momento di estrarre i file effettivi, invece di cercare di caricare un "set" da un unico "file di risorse", ho semplicemente estratto i dati da ciascuna risorsa incorporata, come questa:

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

Questo nuovo modo sostanzialmente significa che si dice al compilatore che "sono necessari per l'exe questi file e sono incorporati", in modo che quando si chiama il "costruire" il comando, lo fa in realtà tutto il lavoro per voi e legge i file come array di byte e li incorpora nel file eseguibile.

Quindi, d'altra parte, si indica semplicemente al programma che si desidera salvare le risorse incorporate come file, utilizzando i propri nomi di file.

Speriamo che questo aiuti qualcun altro che sta provando a fare questo ... come ogni altro post per questo tipo di domanda aveva alcune risposte troppo complicate che erano incomplete (ad esempio: come incorporare, ma non recuperare) o didn ' in realtà funziona.

Problemi correlati