如何更新大量资源?

时间:2013-07-16 08:24:49

标签: c# winapi resources

我想将许多资源添加到exe。我注意到我只能通过一些资源这样做:

// BeginUpdate();
// for (int i = 0; i < count; i++)
//     UpdateResource();
// EndUpdate();

因为WinApi中似乎有一个bug或者什么。我现在正试着这样做:

// for (int i = 0; i < count; i++)
// {
//     BeginUpdate();
//     UpdateResource();
//     EndUpdate();
// }

当然它不会发生。 GetLastError()会返回有时错误代码5(访问被拒绝)和110(系统无法打开指定的设备或文件。) 。它适用于某些资源,然后错误110成组。有时错误5会出现。我该如何解决这些错误?我必须添加1000多个资源,并且该函数必须完全成功或失败,之间没有任何内容。

<小时/> 这是我的函数,它只是添加随机字符串:

[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern IntPtr BeginUpdateResource([MarshalAs(UnmanagedType.LPStr)] string filename, bool deleteExistingResources);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool UpdateResource(IntPtr resource, [MarshalAs(UnmanagedType.LPStr)] string type, [MarshalAs(UnmanagedType.LPStr)] string name, ushort language, IntPtr data, uint dataSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EndUpdateResource(IntPtr resource, bool discardChanges);

private static void addResources(string filename, int count)
{
    // 1. delete existing resources
    IntPtr handle = BeginUpdateResource(filename, true);
    Console.WriteLine(EndUpdateResource(handle, false));

    // 2. add resources
    for (int i = 0; i < count; i++)
    {
        handle = BeginUpdateResource(filename, false);
        string text = Utils.randomString(16);
        if (!UpdateResource(handle, "TEST", "" + i, 0, Marshal.StringToHGlobalAnsi(text), (uint) text.Length))
            Console.WriteLine("update error: " + GetLastError() + ", " + i);
        if (!EndUpdateResource(handle, false))
            Console.WriteLine("endupdate error: " + GetLastError() + ", " + i);
    }
}

2 个答案:

答案 0 :(得分:1)

似乎只有一种方法可以解决此错误:重试

EndUpdateResource(...)无缘无故地失败(程序员的观点)。原因可能是AnitVir或Windows检查文件。它可能会连续几次或多次失败。特别是当你多次修改资源时会发生这种情况。

解决方案:重试从BeginUpdateResource(...)EndUpdateResource(...)的所有内容

if (EndUpdateResource(...))
    // success
else
    // retry

答案 1 :(得分:0)

你的代码错了。您正在循环中调用BeginUpdateResource()EndUpdateResource()。它应该只是:

handle = BeginUpdateResource(...);
for(...) {
   UpdateResource(...);
}
EndUpdateResource(...);

随着UpdateResource()累积的更改将被一起写入(这是EndUpdateResource()的工作),因此它为您提供“全有或全无”的语义。

有关详情,请参阅UpdateResource()文档的备注部分: http://msdn.microsoft.com/en-us/library/windows/desktop/ms648049%28v=vs.85%29.aspx