1

我想向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);
    }
}
4

2 回答 2

1

Seems there is only 1 way around this error: RETRYING

EndUpdateResource(...) tends to fail for no reason (view of the programmer). Reason might be AnitVir or Windows checking the file. It can fail a few or lots of times in a row. Happens especially when you modify resources more than once.

Solution: Retry everything from BeginUpdateResource(...) to EndUpdateResource(...)

if (EndUpdateResource(...))
    // success
else
    // retry
于 2013-07-17T10:12:08.857 回答
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

于 2013-07-16T09:11:36.353 回答