Solved! See below.
I have 2 C# applications. Application a is supposed to modify the internal resources of application b. Application b is supposed to do something with its (modified) resources when executed.
How can I accomplish that?
Here is what I tried:
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);
}
}
}
I get a System.ArgumentException with The stream is readonly. on System.Resources.ResourceWriter..ctor(Stream stream)
EDIT
Since that does not seem to be possible with .net resources: Is there any other way?
I want to produce a single file (namely the exe of application b) which is executable and can work with the data (stored in the exe) that is given prior to execution from application a. Preferably without having to actually compile b in order to give it the data.
Assumptions in order to make it a little easier:
ais always executed beforebais only executed once- both applications are written by me
Edit - Sollution
Since it is not possible to accomplish that via resources I used the following workaround:
Apparently you can append ANYTHING to an exe file and it will still be executable, so here is what I came up with:
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();
}
}
If you want to use this snippet go ahead but note that if you add data to a file the indexes are in reverse order when retrieving:
Let's say you write data set A first and then data set B, if you read the data later B will have the index 0 and A the index 1.