5

我在使用 FileVersionInfo.GetVersionInfo() 时遇到了一些严重的怪异现象,希望有人能提供帮助。

问题的基础是我正在遍历一个文件夹中的所有文件,每个文件都调用 GetVersionInfo()。大约有300个文件。这适用于除 2 个文件之外的所有文件。对于这些 DLL,我从 GetVersionInfo() 返回的信息完全不正确。

为了消除所有其他变量,我将此调用提取到一个简单的测试应用程序中,它仍然遇到同样的问题。但是,如果我将测试应用程序构建为 Windows 应用程序(最初是控制台应用程序),那么数据就会正确返回。

澄清一下,作为控制台应用程序运行时返回的不正确数据不仅仅是文件不包含版本数据时所获得的空信息。它包含合理的数据,但只是错误的数据。就好像它正在从不同的文件中读取它一样。我寻找了一个包含匹配版本数据的文件,但找不到。

如果构建为控制台应用程序而不是 Windows 应用程序,为什么这个简单的调用会以不同的方式运行?

如果有人可以提供帮助,我将不胜感激。

Rgds,安迪

-- 添加代码

using System;
using System.Diagnostics;

namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            string file = "C:\\ProblemFile.dll";
            FileVersionInfo version = FileVersionInfo.GetVersionInfo(file);
            string fileName = version.FileName;
            string fileVersion = version.FileVersion;

            Console.WriteLine(string.Format("{0} : {1}", fileName, fileVersion));
        }
    }
}
4

4 回答 4

8

这种行为确实很奇怪。可能是控制台应用程序没有从与 WinForms 应用程序相同的位置加载 DLL 吗?这意味着它GetVersionInfo使用了除 Win32 之外的其他 API CreateFile(可能通过一些 DLL 解析器机制,并排或其他);请记住,在幕后,version.dll将执行您的请求,而不是 CLR 本身。

FileVersionInfo通过反射器看另一个方向:

public static unsafe FileVersionInfo GetVersionInfo(string fileName)
{
    // ...
    int fileVersionInfoSize = UnsafeNativeMethods.GetFileVersionInfoSize(fileName, out num);
    FileVersionInfo info = new FileVersionInfo(fileName);
    if (fileVersionInfoSize != 0)
    {
        byte[] buffer = new byte[fileVersionInfoSize];
        fixed (byte* numRef = buffer)
        {
            IntPtr handle = new IntPtr((void*) numRef);
            if (!UnsafeNativeMethods.GetFileVersionInfo(fileName, 0, fileVersionInfoSize, new HandleRef(null, handle)))
            {
                return info;
            }
            int varEntry = GetVarEntry(handle);
            if (!info.GetVersionInfoForCodePage(handle, ConvertTo8DigitHex(varEntry)))
            {
                int[] numArray = new int[] { 0x40904b0, 0x40904e4, 0x4090000 };
                foreach (int num4 in numArray)
                {
                    if ((num4 != varEntry) && info.GetVersionInfoForCodePage(handle, ConvertTo8DigitHex(num4)))
                    {
                        return info;
                    }
                }
            }
        }
    }
    return info;
}

如您所见,代码页正在发生一些有趣的舞蹈。如果您检查的 DLL 附加了多个版本信息资源怎么办?根据调用程序的文化GetVersionInfo,我猜与代码页相关的调用可能会返回其他结果?

花时间检查 DLL 的资源并确保版本信息只有一种语言/代码页。我希望它可能会为您指出解决方案。

于 2010-02-10T06:11:00.957 回答
0

当然,您看到的“文件”不是 . 和 .. ?如果您遍历所有文件,您将始终看到 . (当前目录)和..(上目录)。GetVersion Info 可能会为这些返回任何内容。您必须按名称手动过滤这些条目。

于 2010-02-08T13:01:08.860 回答
0

文件和程序集版本是两个不同的东西。

你确定你不期待另一个?

于 2010-02-08T13:47:17.927 回答
0

更新:试过这个。没用。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace test
{
    class Program
    {
        [DllImport("COMCTL32")]
        private static extern int InitCommonControls(int nExitCode);

        static void Main(string[] args)
        {
            InitCommonControls(0);

            string file = "C:\\ProblemFile.dll";
            FileVersionInfo version = FileVersionInfo.GetVersionInfo(file);
            string fileName = version.FileName;
            string fileVersion = version.FileVersion;

            Console.WriteLine(string.Format("{0} : {1}", fileName, fileVersion));
        }
    }
}
于 2010-02-08T16:17:17.343 回答