C# 以编程方式将资源嵌入.NET程序集中
我有一个已编译的.NET程序集,其中嵌入了一个特定的资源文件(名为“Script.xml”)。我需要通过编程将其更改为另一个 这是否可以在不从源代码重新编译的情况下实现 目前,我做了一个文本搜索,我知道是在文件中,它工作得很好。但我需要为另一个项目这样做,我不知道资源文件的任何内容,我需要找到另一种方法C# 以编程方式将资源嵌入.NET程序集中,c#,compiler-construction,resources,C#,Compiler Construction,Resources,我有一个已编译的.NET程序集,其中嵌入了一个特定的资源文件(名为“Script.xml”)。我需要通过编程将其更改为另一个 这是否可以在不从源代码重新编译的情况下实现 目前,我做了一个文本搜索,我知道是在文件中,它工作得很好。但我需要为另一个项目这样做,我不知道资源文件的任何内容,我需要找到另一种方法 FileStream exe = new FileStream(currentexe, FileMode.Open); //find xml part of exefile string fi
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();
FileStream exe=newfilestream(currentexe,FileMode.Open);
//查找exefile文件的xml部分
字符串find=“”;
字符串lastchars=新字符串(“”,find.Length);
while(exe.CanRead){
lastchars=lastchars.Substring(1)+(char)exe.ReadByte();
if(lastchars==find){
Seek(-find.Length,SeekOrigin.Current);
打破
}
}
//输出序列化脚本
int bytenum=0;
foreach(xml中的字节c){
如果(c==0)中断;
exe.WriteByte(c);
bytenum++;
}
//清除额外数据
while(bytenum++
您当前的机制非常脆弱-它不适用于已签名的程序集(因为散列将发生变化),或者如果您需要将一个资源替换为一个较大的资源(因为所有其他偏移都可能移动)。它在字符编码和在文件中找到正确点的一般机制方面也存在问题,但鉴于我认为这种方法不适合开始,这些问题相对来说并不重要
如果您需要可替换资源,我会将它们放在一个不同的文件中,该文件没有相对精细的程序集格式。您可能正在寻找System.Runtime.Emit来动态编译程序集。您可以使用反射动态构建程序集,特别是
AssemblyBuilder
类,并在动态构建的程序集中包含资源。我不确定是否可以使用反射来分解现有的程序集(尽管现在我很感兴趣)
如果可能的话,我会叫另一棵树。您可以使用
Cecil
打开程序集并插入资源(我会)。YMMV资源文件可以变得更大,而且仍然可以工作,因为它可以用空格填充(最大大小为:“ScriptFileSize”)。不幸的是,对于这个项目,它需要包含在一个文件中。@Nick:这实际上是说它不能大于现有资源,因为现有资源总是脚本文件大小。我会真的,真的尝试重新设计这个。如果一定要这样做,请使用一个知道程序集文件格式的库(如Cecil-),但尽可能避免这样做。@Jon:是的,我忘了提到程序集最初编译时已经有大量的填充以匹配const ScriptFileSize。我提供了大量的空间,从未用完过,目前已经成功地在数百台计算机上运行。但我真的,真的很想重新设计它,这就是我在这里发帖的原因。如果你使用Cecil正确读取和重新生成PDB,它不会破坏PDB。我猜是这样的,但1.5年前我不知道怎么做。你有一个例子吗?那时候它已经在起作用了。但是现在有了新的API,您可以在这里看到: