In my function GetAssemblyResourceStream (code below), I read resource from Dll using "assembly.GetManifestResourceStream" and "resourceReader.GetResourceData".
When I set my memory stream from the byte array of the resource, I have to include an offset of 4 bytes:
const int OFFSET = 4;
resStream = new MemoryStream(data, OFFSET, data.Length - OFFSET);
What is the reason of that offset? where does it came from?
Reference: Sample at end of MSDN ResourceReader Class
Also: I made a test app to better understand resources. That app show the problem I had with the offset. My little test app is available at Github (VS 2015)
Update 2015-10-05 10h28 Due to very low answers, I suspected a bug and/or undocumented behavior. I reported a bug at Connect.Microsoft.com and will see the result.
Update 2015-10-07 I removed the bug. I still think it is not well documented and/or could be considered as a bug but I highly suspect they will close my request without doing anything. I hope nobody will fall in the same problem I did.
Code:
// ******************************************************************
/// <summary>
/// The path separator is '/'. The path should not start with '/'.
/// </summary>
/// <param name="asm"></param>
/// <param name="path"></param>
/// <returns></returns>
public static Stream GetAssemblyResourceStream(Assembly asm, string path)
{
// Just to be sure
if (path[0] == '/')
{
path = path.Substring(1);
}
// Just to be sure
if (path.IndexOf('\\') == -1)
{
path = path.Replace('\\', '/');
}
Stream resStream = null;
string resName = asm.GetName().Name + ".g.resources"; // Ref: Thomas Levesque Answer at:
// https://mcmap.net/q/721413/-enumerating-net-assembly-resources-at-runtime
using (var stream = asm.GetManifestResourceStream(resName))
{
using (var resReader = new System.Resources.ResourceReader(stream))
{
string dataType = null;
byte[] data = null;
try
{
resReader.GetResourceData(path.ToLower(), out dataType, out data);
}
catch (Exception ex)
{
DebugPrintResources(resReader);
}
if (data != null)
{
switch (dataType) // COde from
{
// Handle internally serialized string data (ResourceTypeCode members).
case "ResourceTypeCode.String":
BinaryReader reader = new BinaryReader(new MemoryStream(data));
string binData = reader.ReadString();
Console.WriteLine(" Recreated Value: {0}", binData);
break;
case "ResourceTypeCode.Int32":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToInt32(data, 0));
break;
case "ResourceTypeCode.Boolean":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToBoolean(data, 0));
break;
// .jpeg image stored as a stream.
case "ResourceTypeCode.Stream":
////const int OFFSET = 4;
////int size = BitConverter.ToInt32(data, 0);
////Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
////Console.WriteLine(" Recreated Value: {0}", value1);
const int OFFSET = 4;
resStream = new MemoryStream(data, OFFSET, data.Length - OFFSET);
break;
// Our only other type is DateTimeTZI.
default:
////// No point in deserializing data if the type is unavailable.
////if (dataType.Contains("DateTimeTZI") && loaded)
////{
//// BinaryFormatter binFmt = new BinaryFormatter();
//// object value2 = binFmt.Deserialize(new MemoryStream(data));
//// Console.WriteLine(" Recreated Value: {0}", value2);
////}
////break;
break;
}
// resStream = new MemoryStream(resData);
}
}
}
return resStream;
}