c# - 更新 exe 资源部分中的图像(在 c#/C 中)

标签 c# resources .net-2.0

我在资源部分的可执行文件中嵌入了很少的图像。 我按照以下步骤创建了我的可执行文件:

  1. 使用一些实用程序为目录中的所有图像 (.jpg) 生成 .resx 文件。图片命名为image1.jpg、image2.jpg等。
  2. 使用以下方法从 .resx 文件创建 .resources 文件:resgen myResource.resx
  3. 使用/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/

相关文章:

Java - getResource 在 csv 文件上失败

c# - 基于文件的 ResourceManager 如何回退到嵌入式资源?

c# - ASP.NET 网页 -> 显示静态信息的最佳方式

c# - 如何在 wpf 后台执行任务,同时能够提供报告并允许取消?

c# - 如何使用 C# 从 pfx 文件中检索证书?

c# - 带有 EF 的 ASP.NET 成员提供程序

c# - 新的 .NET 运行时能否抛出更有意义的空引用异常?

c++ - 使用 SFML 资源管理器的 C++ 模板

c# - 在 C# 中比较两个数据集

c# - 如何序列化到日期时间