我在资源部分的可执行文件中嵌入了很少的图像。 我按照以下步骤创建了我的可执行文件:
- 使用一些实用程序为目录中的所有图像 (.jpg) 生成 .resx 文件。图片命名为image1.jpg、image2.jpg等。
- 使用以下方法从 .resx 文件创建 .resources 文件:
resgen myResource.resx
- 使用/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
片段代码成功读取这些资源。
Win32 资源是另一种野兽,它与一般的托管 .NET 世界不太“兼容”,尽管您确实可以使用 /win32Res
参数将它们添加到 .NET exe - 注意细微差别:-)
现在,如果你想修改嵌入式 .NET 资源,我认为框架本身没有类可以做到这一点,但是你可以使用 Mono.Cecil图书馆代替。这里有一个例子可以证明这一点:C# – How to edit resource of an assembly?
如果你想修改嵌入式 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);
}
}
关于c# - 更新 exe 资源部分中的图像(在 c#/C 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9349784/