2009-07-10 6 views
7

J'ai un assembly .NET compilé avec un fichier de ressources spécifique incorporé (nommé 'Script.xml'). J'ai besoin de le changer par programme pour un autre.Intégration programmée de ressources dans un assembly .NET

Est-ce possible sans recompilation de la source?

Actuellement, je fais une recherche de texte que je sais est dans le fichier et cela fonctionne bien. Mais je dois le faire pour un autre projet où je ne connais pas le contenu du fichier de ressources et j'ai besoin de trouver une autre méthode.

FileStream exe = new FileStream(currentexe, FileMode.Open); 

//find xml part of exefile 
string find = "<?xml version=\"1.0\"?>"; 
string lastchars = new string(' ', find.Length); 
while (exe.CanRead) { 
    lastchars = lastchars.Substring(1) + (char)exe.ReadByte(); 
    if (lastchars == find) { 
     exe.Seek(-find.Length, SeekOrigin.Current); 
     break; 
    } 
} 

//output serialized script 
int bytenum = 0; 
foreach (byte c in xml) { 
    if (c == 0) break; 
    exe.WriteByte(c); 
    bytenum++; 
} 

//clean out extra data 
while (bytenum++ < ScriptFileSize) { 
    exe.WriteByte(0x20); 
} 
exe.Close(); 

Répondre

4

Vous pouvez utiliser Cecil pour ouvrir l'assemblage et insérer une ressource (oui). YMMV

+1

Il ne casse pas les PDB si vous utilisez Cecil pour lire correctement et régénérer les PDB. –

+0

Je devinais que c'était le cas, mais il y a 1,5 ans je ne pouvais pas comprendre comment le faire. Avez-vous un exemple? –

+0

Il fonctionnait déjà à l'époque. Mais de nos jours, avec les nouvelles API, vous devriez l'indiquer ici: https://github.com/jbevain/cecil/wiki/Debug-symbols –

4

Votre mécanisme actuel est très fragile - il ne fonctionnera pas pour les assemblées signés (comme le hachage change) ou si vous avez besoin de remplacer une ressource avec une plus grande (comme tous les autres décalages peuvent se déplacer) . Il y a aussi des problèmes en termes de codages de caractères et le mécanisme général pour trouver le bon point dans le fichier de toute façon, mais ceux-ci sont relativement sans importance étant donné que je ne pense pas que l'approche soit appropriée pour commencer.

Si vous avez besoin de ressources remplaçables, je les mettrais tout à fait dans un fichier différent, qui n'a pas le format relativement délicat d'un assemblage.

+0

Le fichier de ressources peut grossir et fonctionne toujours car il peut être complété avec des espaces (jusqu'à une taille maximale: 'ScriptFileSize'). Et malheureusement, il doit être contenu dans un seul fichier pour ce projet. –

+0

@Nick: Cela signifie en fait qu'il ne peut pas être plus grand que la ressource existante, car la ressource existante sera toujours ScriptFileSize. J'essaierais vraiment, vraiment, de le redessiner. Si vous devez absolument le faire, utilisez une bibliothèque qui connaît le format du fichier d'assemblage (comme Cecil - http://www.mono-project.com/Cecil) mais essayez d'éviter de le faire si cela est possible. –

+0

@Jon: Vrai, j'ai oublié de mentionner que l'assemblage est à l'origine compilé avec une tonne de remplissage déjà là pour correspondre à la script ScriptFileSize. Je donne beaucoup d'espace et je n'en ai jamais manqué et cela fonctionne actuellement sur des centaines d'ordinateurs avec succès. Mais je veux vraiment, vraiment le redessiner, c'est pourquoi je poste ici. –

1

Vous recherchez probablement System.Runtime.Emit pour compiler dynamiquement un assembly.

1

Vous pouvez créer dynamiquement des assemblages à l'aide de la réflexion, en particulier de la classe AssemblyBuilder, et inclure des ressources dans votre assemblage construit dynamiquement. Je ne suis pas sûr qu'il soit possible de démonter un assemblage existant en utilisant la réflexion (même si cela m'intéresse maintenant).

Je aboyerais un autre arbre si possible.

Questions connexes