有没有办法在不重建的情况下更新dll文件的文件版本?

问题描述 投票:0回答:1

我的一些 .dll 文件包含错误的版本号。我想用正确的值更新这些版本而不重建。我找到了这个 UpdateResource 函数,并尝试使用 Platform Invoke 来实现它。
这是我到目前为止所拥有的:

public class UpdateBinaryResource {

class VersionResourceUpdater
{
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr BeginUpdateResource(string pFileName, bool bDeleteExistingResources);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool UpdateResource(IntPtr hUpdate, IntPtr lpType, IntPtr lpName, ushort wLanguage, byte[] lpData, uint cbData);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);

    [StructLayout(LayoutKind.Sequential)]
    private struct VS_FIXEDFILEINFO
    {
     public uint dwSignature;
     public uint dwStrucVersion;
     public uint dwFileVersionMS;
     public uint dwFileVersionLS;
     public uint dwProductVersionMS;
     public uint dwProductVersionLS;
     public uint dwFileFlagsMask;
     public uint dwFileFlags;
     public uint dwFileOS;
     public uint dwFileType;
     public uint dwFileSubtype;
     public uint dwFileDateMS;
     public uint dwFileDateLS;
 }

    public static bool UpdateVersionInfo(string filePath, string productVersion, string fileVersion)
    {

        string[] fileVersionParts = fileVersion.Split('.');
        string[] productVersionParts = productVersion.Split('.');
        Console.WriteLine(fileVersionParts[0]);
        // combine parts to 32-bit uInt
        VS_FIXEDFILEINFO fileInfo = new VS_FIXEDFILEINFO
        {
            dwSignature = 0xFEEF04BD,
            dwStrucVersion = 0x00010000,
            dwFileVersionMS = (uint.Parse(fileVersionParts[0]) << 16) | uint.Parse(fileVersionParts[1]),
            dwFileVersionLS = (uint.Parse(fileVersionParts[2]) << 16) | uint.Parse(fileVersionParts[3]),
            dwProductVersionMS = (uint.Parse(productVersionParts[0]) << 16) | uint.Parse(productVersionParts[1]),
            dwProductVersionLS = (uint.Parse(productVersionParts[2]) << 16) | uint.Parse(productVersionParts[3]),
            dwFileFlagsMask = 0x3F,
            dwFileFlags = 0,
            dwFileOS = 0x40004,
            dwFileType = 0x1,
            dwFileSubtype = 0x0,
            dwFileDateMS = 0,
            dwFileDateLS = 0
        };
        Console.WriteLine(fileInfo.dwFileVersionMS);
        var fileInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(fileInfo));
        Marshal.StructureToPtr(fileInfo, fileInfoPtr, false);

        IntPtr hUpdate = BeginUpdateResource(filePath, false);
        if (hUpdate == IntPtr.Zero)
        {
            int error = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(error, $"Failed to open file for updating: {filePath}. Error code: {error}");
        }

        byte[] fileInfoBytes = new byte[Marshal.SizeOf(fileInfo)];
        Marshal.Copy(fileInfoPtr, fileInfoBytes, 0, fileInfoBytes.Length);

        if (!UpdateResource(hUpdate, new IntPtr(16), new IntPtr(1), 0, fileInfoBytes, (uint)fileInfoBytes.Length))
        {
            int error = Marshal.GetLastWin32Error();
            EndUpdateResource(hUpdate, false);
            throw new System.ComponentModel.Win32Exception(error, $"Failed to update resource. Error code: {error}");
        }

        if (!EndUpdateResource(hUpdate, false))
        {
            int error = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(error, $"Failed to end resource update. Error code: {error}");
        }

        Marshal.FreeHGlobal(fileInfoPtr);

        return true;
    }
}
class Program
{
    static void Main(string[] args)
    {
        string dllPath =  @"C:\Users\user\Desktop\temp.dll";
        string productVer = "23.0.3.0";
        string fileVer = "23.0.3.1";

        var UpdateBinaryResource = VersionResourceUpdater.UpdateVersionInfo(dllPath, productVer, fileVer);

        Console.WriteLine("Success");
    }
}
}

运行后,我检查了dll文件属性中的详细信息部分,发现它只删除了以前存在的值,而不是用新值更新版本。
是否可以在不重建的情况下更新版本号?如果可以,可以通过 C# 完成吗?

c# .net dll
1个回答
0
投票

也需要这个。我发现的唯一解决方案是在内存中构建我自己的 VS_VERSION_INFO 数据结构并将缓冲区传递给

UpdateResource(hUpdate, RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO), languageID, &buffer, buffer.size());

这个日语博客上的代码对此进行了很好的解释(只需在浏览器中使用翻译):https://espresso3389.hatenablog.com/entry/20100907/1283788958

© www.soinside.com 2019 - 2024. All rights reserved.