更新exe资源部分中的图像(在c#/ C中)
我在资源部分的可执行文件中嵌入了很少的图像。 我按照以下步骤创建了我的可执行文件:
- 使用某个实用程序为目录中的所有图像(.jpg)生成.resx文件。 图像命名为image1.jpg,image2.jpg等。
- 使用:
resgen myResource.resx
从.resx文件创建.resources文件 - 使用/ res标志嵌入生成的.resource文件:
csc file.cs /res:myResource.resources
4我正在访问这些图像:
ResourceManager resources = new ResourceManager("myResource", Assembly.GetExecutingAssembly()); Image foo = (System.Drawing.Image)(resources.GetObject("image1"));
这一切都按预期正常工作。 现在我想将嵌入的图像更改为一些新图像。 这就是我目前正在做的事情:
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()); } } }
上面的代码是为指定的图像添加一个新资源(在IMAGE
标题内部有一些随机数,如Resource hacker
),但我想修改image1
的现有资源数据。
我确信我使用一些无效的参数调用UpdateResource
。
任何人都可以指出这一点吗?
我使用的是.NET版本2
谢谢,
维克拉姆
我认为你在.NET资源和Win32资源之间混淆了。 使用/res
参数嵌入到csc.exe
中的资源是.NET资源,您可以使用ResourceManager
代码段成功读取这些ResourceManager
。
Win32资源是另一种野兽,一般来说与托管的.NET世界并不太“兼容”,尽管你确实可以使用/win32Res
参数将它们添加到.NET exe中 – 请注意细微差别:-)
现在,如果您想修改嵌入式.NET资源,我认为在框架本身中没有类可以执行它,但您可以使用Mono.Cecil库。 这里有一个例子可以certificate这一点: C# – 如何编辑程序集的资源?
如果你想修改嵌入式Win32资源,你的代码需要一些修复,这里是一个稍微修改过的版本,最重要的区别在于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); } }
这是不可能的。 您无法修改正在运行的编译文件。
我相信您可以在运行时添加新图像,但无法更新基本上只保留在内存中的资源。
如果你在运行时添加一个资源,它存在,但我不认为它是编译的,因此我不认为你可以访问它。
您是否有理由不使用内容?