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.