4

我使用FileVersionInfo.GetVersionInfo()得到了一些严重的奇怪,并希望有人能够帮助。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)); 
     } 
    } 
} 
+0

如何张贴展示问题的简化代码... – 2010-02-08 12:52:02

+0

感谢米奇,现在添加。正如你所看到的,它没有做任何特别的事情。当它构建为控制台应用程序或Windows应用程序时,我会得到不同的结果。 (显然作为一个Windows应用程序Console.WriteLine不起作用,但我可以看到带有断点的结果。) 我只在一些DLL上遇到问题,其他一切正常。我不知道DLL的任何特殊之处,它们是公司中另一个团队的输出。 如果有帮助,请使用VS2005/.NET 2.0。 – Andy 2010-02-08 13:35:31

+0

注意:**我是**使用VS2005/.NET 2.0。问题DLL是VS6.0 C++ – Andy 2010-02-08 15:20:56

回答

8

这种行为确实很奇怪。难道控制台应用程序不能像WinForms应用程序那样从同一个地方加载DLL吗?这意味着GetVersionInfo使用一些其他的API,而不仅仅是Win32 CreateFile(可能会经历一些DLL解析器机制,并排或其他);请记住,在封面下,version.dll将执行您的请求,而不是CLR本身。

在另一个方向看FileVersionInfo通过Reflector尚未点:

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

+0

谢谢皮埃尔,你肯定似乎在这里。有问题的DLL有两个版本资源,一个en-GB和一个en-US。美国版本中包含正确的数据。将我的文化改为en-US确实使控制台应用程序能够获取en-US版本。但是,即使当我的文化是en-GB时,Windows App也会获得en-US版本。任何想法为什么会发生? – Andy 2010-02-11 12:17:24

+0

嗨,安迪。如果你觉得它有用,我建议你点击upvote按钮来获得答案。这就是StackOverflow的工作原理;-)。不,唉,我不知道文化是如何派生出来的。您可以尝试访问'System.Threading.Thread.CurrentThread.CurrentCulture'并比较控制台和WinForms应用程序之间的结果。 – 2010-02-11 15:38:28

+0

现在已经这样做了。之前没有足够的代表!看过CurrentCulture和CurrentUICulture,它们在控制台和Windows中都是一样的(分别是en-GB和en-US)。将它们更改为en-US将更改控制台应用程序,但似乎没有更改Windows应用程序。它仍然留下问题,但它给我足够的工作与这两个DLL。谢谢你的帮助。 – Andy 2010-02-11 15:48:50

0

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

+0

感谢鲍勃,但是我确信事实并非如此。在我提到的测试应用程序中,我已经对文件名进行了硬编码,并且只是在其中一个问题文件上调用GetVersion()一次。 – Andy 2010-02-08 13:22:24

0

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

你确定你不期待其他?

+0

不确定组装版本。 当我查看FileVersionInfo时,我可以看到FileVersion和ProductVersion。当我构建为控制台应用程序时,这些都是“1,0,0,1”。当我构建为Windows应用程序时,它们都是“4,2,004,6102”。如果从Windows资源管理器中提取属性并查看版本选项卡,其他版本信息,则文件版本和产品版本都显示为“4,2,004,6102”。 – Andy 2010-02-08 13:53:37

+0

您在'AssemblyInfo.cs'中应用了2个不同的属性,也许它们是不同的。这就是我能想到的。 – leppie 2010-02-08 13:57:04

+0

啊,我可以看到,在我的项目中,但它不显示在问题DLL的属性窗格中。这些不是.NET dll,我认为它们是VS6.0 C++ – Andy 2010-02-08 14:09:46

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)); 
     } 
    } 
} 
相关问题