【发布时间】:2014-09-30 14:36:28
【问题描述】:
解决了!见下文。
我有 2 个 C# 应用程序。应用程序 a 应该修改应用程序 b 的内部资源。应用程序 b 应该在执行时对其(修改的)资源做一些事情。
我怎样才能做到这一点?
这是我尝试过的:
public static void addFileToResources(string dest, string src)
{
Assembly a_dest = Assembly.LoadFile(dest);
using (Stream s_dest = a_dest.GetManifestResourceStream("Elevator.Properties.Resources.resources"))
{
using (ResourceWriter rw = new ResourceWriter(s_dest))
{
byte[] b_src = File.ReadAllBytes(src);
rw.AddResource("target", b_src);
}
}
}
我在System.Resources.ResourceWriter..ctor(Stream stream) 上收到System.ArgumentException 和The stream is readonly.
编辑
由于 .net 资源似乎无法做到这一点:还有其他方法吗?
我想生成一个文件(即应用程序b 的exe),它是可执行的,并且可以使用在应用程序a 执行之前给出的数据(存储在exe 中)。最好不必为了给它数据而实际编译b。
为了使它更容易一些假设:
-
a总是在b之前执行 -
a只执行一次 - 这两个应用程序都是我编写的
编辑 - 解决方案
由于无法通过资源来实现这一点,因此我使用了以下解决方法:
显然你可以将任何东西附加到一个 exe 文件中,它仍然是可执行的,所以这就是我想出的:
public class Packer : IDisposable
{
// chosen quite arbitrarily; can be anything you'd like but should be reasonably unique
private static byte[] MAGIC_NUMBER = { 0x44, 0x61, 0x6c, 0x65, 0x6b, 0x4c, 0x75, 0x63 };
private Stream inStream;
public Packer(string filename, bool openReadonly = false)
{
// The FileAccess.Read is necessary when I whant to read from the file that is being executed.
// Hint: To get the path for the executing file I used:
// System.Reflection.Assembly.GetExecutingAssembly().Location
inStream = File.Open(filename, FileMode.Open, openReadonly ? FileAccess.Read : FileAccess.ReadWrite, openReadonly ? FileShare.Read : FileShare.None);
}
public byte[] ReadData(int index)
{
byte[] mn_buf = new byte[MAGIC_NUMBER.Length];
byte[] len_buf = new byte[sizeof(Int32)];
int data_len = 0;
inStream.Seek(0, SeekOrigin.End);
for (int i = 0; i <= index; ++i)
{
// Read the last few bytes
inStream.Seek(-MAGIC_NUMBER.Length, SeekOrigin.Current);
inStream.Read(mn_buf, 0, MAGIC_NUMBER.Length);
inStream.Seek(-MAGIC_NUMBER.Length, SeekOrigin.Current);
for (int j = 0; j < MAGIC_NUMBER.Length; ++j)
{ // Check if the last bytes are equals to my MAGIC_NUMBER
if (mn_buf[j] != MAGIC_NUMBER[j])
{
throw new IndexOutOfRangeException("Not enough data.");
}
}
inStream.Seek(-sizeof(Int32), SeekOrigin.Current);
inStream.Read(len_buf, 0, sizeof(Int32));
inStream.Seek(-sizeof(Int32), SeekOrigin.Current);
// Read the length of the data
data_len = BitConverter.ToInt32(len_buf, 0);
inStream.Seek(-data_len, SeekOrigin.Current);
}
byte[] data = new byte[data_len];
// Read the actual data and return it
inStream.Read(data, 0, data_len);
return data;
}
public void AddData(byte[] data)
{
// append it
inStream.Seek(0, SeekOrigin.End);
inStream.Write(data, 0, data.
inStream.Write(BitConverter.GetBytes(data.Length), 0, sizeof(Int32));
inStream.Write(MAGIC_NUMBER, 0, MAGIC_NUMBER.Length);
}
public void Dispose()
{
inStream.Dispose();
}
}
如果您想使用这个 sn-p 继续,但请注意,如果您将数据添加到文件中,则检索时索引的顺序是相反的:
假设你先写数据集A,然后再写数据集B,如果你再读数据,B的索引为0,A的索引为1。
【问题讨论】:
-
您是否验证过您将非空值传递给
ResourceWriter的构造函数? -
两个问题。您没有正确猜测资源流名称,这就是导致异常的原因。当你解决这个问题时,你会遇到更严重的问题,资源在嵌入到 .NET 程序集中后是只读的。重建可执行文件是不切实际的。
-
嗯...该死的。还是谢谢!
-
你必须使用外部资源文件。如果
b是您的应用程序,那么您可以实现自己的资源管理器来加载外部资源文件如果它存在,否则使用内置。 -
那是我想要避免的。我想把它们都放在一个文件中。
标签: c# resources .net-assembly