FileVersionInfo.FileVersion возвращает ProductVersion?

Я пытаюсь получить версию файла, используя C#:

string file = @"C:\somefile.dll";
Console.WriteLine(FileVersionInfo.GetVersionInfo(file).FileVersion);

Для большинства файлов это хорошо, однако для некоторых я получаю результаты, которые отличаются от представленных в проводнике Windows.

См. Прикрепленное изображение: версия файла, представленная в окнах, - "0.0.0.0", однако та, которую я получаю, используя свойство FileVersion, - "000.000.000.000".

Я пытался использовать разные версии.NET (2, 3.5, 4), которые дают одинаковые результаты.

Кто-нибудь еще сталкивался с этой проблемой?

Спасибо Лиор

3 ответа

Решение

Кажется, Windows Explorer удаляет первые 0 из частей версии.

Попробуйте создать сборку с FileVersion 001.001.001.001, в проводнике она будет отображаться как 1.1.1.1. Но ваш код вернет фактическое значение (001.001.001.001).

РЕДАКТИРОВАТЬ:

Проводник вернет 001.001.001.001 как ProductVersion, но только если AssemblyInformationalVersion не установлен, и в этом случае он вернет это как ProductVersion.

Причина в том, что в WIN32 API (и метаданных файла) версии продукта определяются как строковые, а версии файлов определяются как целочисленные, тогда как в.NET все они определяются как целочисленные.

Если вы используете отражатель и осмотрите FileVersionInfo класс, вы можете видеть, что они загружаются по-разному:

 this.productVersion = GetFileVersionString(memIntPtr, string.Format(CultureInfo.InvariantCulture, format, new object[] { codepage, "ProductVersion" }))

Но:

this.fileMajor = HIWORD(fixedFileInfo.dwFileVersionMS);
this.fileMinor = LOWORD(fixedFileInfo.dwFileVersionMS);
this.fileBuild = HIWORD(fixedFileInfo.dwFileVersionLS);
this.filePrivate = LOWORD(fixedFileInfo.dwFileVersionLS);

Два ответа от 2011 года, в каждом отсутствует часть картины.

Ресурсы информации о версии должны содержать информацию о версии в двоичной форме , а также могут содержать отдельную информацию о версии в строковой форме .

Эти два значения не ограничены совпадением. Действительно, строковые формы даже не обязательно должны быть числовыми и могут содержать любые произвольные текстовые элементы.

В данном случае в файл DLL было скомпилировано следующее:

  • Двоичная форма версии файла имеет четыре слова нулей, аFileMajor,FileMinor,FileBuild, иFilePrivateтаким образом, в конечном итоге получим четыре целых числа с нулевым значением.
  • Строковая форма версии файла буквально представляет собой строку "000.000.000.000"и вот что получается.

Версия продукта не отображается как версия файла. Он показывает строку версии файла (в свободном формате) , а не номера версий файлов (четыре 16-битных слова) .

Первая интересная особенность заключается в том, что строковая форма должна соответствовать текущему языку и кодовой странице во время выполнения программы, считывающей информацию о ресурсах из DLL. Как вы можете видеть из документа, этот механизм позволяет (потенциально) каждому языку + кодовой странице иметь свой собственный переведенный вариант строки версии файла; и API извлекают тот, который соответствует.

Вторая интересная особенность заключается в том, что в диалоговом окне свойств проводника Windows отображается только двоичная форма версии файла. Он просто полностью игнорирует строковую форму. (Это недокументированная причуда Explorer; однако вы найдете упоминание о ней в нескольких раздраженных комментариях Stack Overflow за последнее десятилетие с тех пор, как был задан этот вопрос.) Но информация о версии, зачитаннаяGet-Itemв PowerShell илиSystem.Diagnostics.FileVersionInfoКласс в .NET будет возвращать как строковую, так и двоичную формы, которые компилируются в DLL как отдельные наборы информации.

PowerShell представляет это какFileVersionимущество, которое представляет собойSystem.Stringобъект, созданный из строковой формы, скомпилированной в DLL, иFileVersionRawимущество, которое представляет собойSystem.Versionобъект, созданный из двоичных четырех 16-битных слов, скомпилированных в DLL.

Другие вопросы по тегам