【问题标题】:FileVersionInfo.GetVersionInfo() incorrect in Console ApplicationFileVersionInfo.GetVersionInfo() 在控制台应用程序中不正确
【发布时间】:2011-01-14 08:42:38
【问题描述】:

我在使用 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));
        }
    }
}

【问题讨论】:

  • 如何发布出现问题的缩减代码...
  • 谢谢米奇,现在添加了。如您所见,它没有做任何特别的事情。当它构建为控制台应用程序或 Windows 应用程序时,我会得到不同的结果。 (显然,作为 Windows 应用程序,Console.WriteLine 不起作用,但我可以看到带有断点的结果。)我只在几个 DLL 上遇到问题,其他一切正常。我不知道 DLL 有什么特别之处,它们是公司另一个团队的成果。如果有帮助,请使用 VS2005 / .NET 2.0。
  • 注意:使用 VS2005 / .NET 2.0。问题 DLL 是 VS6.0 C++

标签: c# .net console-application system.diagnostics getfileversion


【解决方案1】:

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

看着FileVersionInfoReflector 指向另一个方向:

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 的资源,并确保版本信息只有一种语言/代码页。我希望它可能会为您指出解决方案。

【讨论】:

  • 谢谢皮埃尔,你肯定似乎在这里有所收获。有问题的 DLL 中有两个版本资源,一个是 en-GB,一个是 en-US。美国版本的数据正确。将我的文化更改为 en-US 确实使控制台应用程序选择了 en-US 版本。但是,即使我的文化是 en-GB,Windows 应用程序也会选择 en-US 版本。知道为什么会发生这种情况吗?
  • 嗨,安迪。如果您觉得它有用,我建议您单击答案的upvote 按钮。这就是 StackOverflow 的工作原理;-)。不,唉,我不知道文化是如何产生的。您可以尝试访问 System.Threading.Thread.CurrentThread.CurrentCulture 并比较控制台和 WinForms 应用程序之间的结果。
  • 现在已经这样做了。之前没有足够的代表!看过 CurrentCulture 和 CurrentUICulture ,它们在控制台和 Windows 中是相同的(分别为 en-GB、en-US)。将它们都更改为 en-US 会更改控制台应用程序,但似乎没有任何改变 Windows 应用程序。它仍然留下了问题,但它给了我足够的能力来处理这两个 DLL。感谢您的帮助。
【解决方案2】:

更新:试过这个。没用。

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));
        }
    }
}

【讨论】:

    【解决方案3】:

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

    你确定你不期待对方吗?

    【讨论】:

    • 不确定程序集版本。当我查看 FileVersionInfo 时,我可以看到 FileVersion 和 ProductVersion。当我构建为控制台应用程序时,它们都是“1、0、0、1”。当我构建为 Windows 应用程序时,两者都是“4、2、004、6102”。如果我从 Windows 资源管理器中提取属性并查看版本选项卡,其他版本信息然后文件版本和产品版本都显示为“4、2、004、6102”。
    • 您在“AssemblyInfo.cs”中应用了 2 个不同的属性,也许它们是不同的。这就是我能想到的。
    • 啊,我可以在我的项目中看到它,但它没有显示在问题 DLL 的属性窗格中。这些不是 .NET dll,我认为它们是 VS6.0 C++
    【解决方案4】:

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

    【讨论】:

    • 谢谢鲍勃,但我确信情况并非如此。在我提到的测试应用程序中,我对文件名进行了硬编码,并且只是在其中一个问题文件上调用 GetVersion()。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2018-06-26
    相关资源
    最近更新 更多