I have few images embedded in my executable in resource section. I followed these steps to create my executable:
resgen myResource.resx
csc file.cs /res:myResource.resources
4 I am accessing these images as:
ResourceManager resources = new ResourceManager("myResource", Assembly.GetExecutingAssembly());
Image foo = (System.Drawing.Image)(resources.GetObject("image1"));
This all is working fine as expected. Now I want to change embedded images to some new images. This is what I am currently doing:
class foo
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, string wLanguage, Byte[] lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
public static void Main(string[] args)
{
IntPtr handle = BeginUpdateResource(args[0], false);
if (handle.ToInt32() == 0)
throw new Exception("File Not Found: " + fileName + " last err: " + Marshal.GetLastWin32Error());
byte[] imgData = File.ReadAllBytes("SetupImage1.jpg");
int fileSize = imgData.Length;
Console.WriteLine("Updaing resources");
if (UpdateResource(handle, "Image", "image1", "image1", imgData, (uint)fileSize))
{
EndUpdateResource(handle, false);
Console.WriteLine("Update successfully");
}
else
{
Console.WriteLine("Failed to update resource. err: {0}", Marshal.GetLastWin32Error());
}
}
}
The above code is adding a new resource for the specified image (inside IMAGE
title with some random number, as seen in Resource hacker
), but I want to modify the existing resource data for image1
.
I am sure that I am calling UpdateResource
with some invalid arguments.
Could any one help pointing that out?
I am using .NET version 2
Thank you,
Vikram
I think you are making a confusion between .NET resources, and Win32 resources. The resources you add embedding with the /res
argument to csc.exe
are .NET resources that you can successfully read using you ResourceManager
snippet code.
Win32 resources are another beast, that is not much "compatible" with the managed .NET world in general, athough you can indeed add them to a .NET exe using the /win32Res
argument - note the subtle difference :-)
Now, if you want to modify embedded .NET resources, I don't think there are classes to do it in the framework itself, however you can use the Mono.Cecil library instead. There is an example that demonstrates this here: C# – How to edit resource of an assembly?
And if you want to modify embedded Win32 resources, you code needs some fixes, here is a slightly modified version of it, the most important difference lies in the declaration of UpdateResource
:
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, short wLanguage, byte[] lpData, int cbData);
[DllImport("kernel32.dll")]
static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
public static void Main(string[] args)
{
IntPtr handle = BeginUpdateResource(args[0], false);
if (handle == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error()); // this will automatically throw an error with the appropriate human readable message
try
{
byte[] imgData = File.ReadAllBytes("SetupImage1.jpg");
if (!UpdateResource(handle, "Image", "image1", (short)CultureInfo.CurrentUICulture.LCID, imgData, imgData.Length))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
EndUpdateResource(handle, false);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With