FileVersionInfo.GetVersionInfo() неверно в консольном приложении
Я получаю некоторые серьезные странности с помощью FileVersionInfo.GetVersionInfo() и надеялся, что кто-нибудь сможет помочь.
Основа проблемы заключается в том, что я перебираю все файлы в папке, вызывающей GetVersionInfo () для каждого. Есть около 300 файлов. Это работает нормально для всех, кроме 2 файлов. Для этих библиотек я получаю совершенно неверную информацию от GetVersionInfo().
Чтобы исключить все остальные переменные, я извлек этот вызов в простое тестовое приложение, и у него все еще возникла та же проблема. Однако если я создал тестовое приложение как приложение Windows (изначально это было консольное приложение), тогда данные вернулись верными.
Просто чтобы уточнить, неверные данные, возвращающиеся при запуске в качестве консольного приложения, - это не просто нулевая информация, как если бы файл не содержал данных о версии. Он содержал разумные данные, но только неверные данные. Это как будто он читает его из другого файла. Я искал файл, который содержит соответствующие данные о версии, но не могу его найти.
Почему этот простой вызов работает по-другому, если он создан как консольное приложение, а не как приложение Windows?
Если кто-то может помочь с этим, я был бы очень благодарен.
Ргдс, Энди
- Код добавлен
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 ответа
Такое поведение действительно кажется странным. Может ли быть так, что консольное приложение не загружает DLL из того же места, что и приложение WinForms? Это будет означать, что GetVersionInfo
использует какой-то другой API, кроме Win32 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 и убедитесь, что для информации о версии существует только одна языковая / кодовая страница. Надеюсь, это поможет вам найти решение.
Обновление: попробовал это. Не сработало
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));
}
}
}
Версии файлов и сборок - это две разные вещи.
Вы уверены, что не ожидаете другого?
Конечно, "файлы", которые вы видите, нет. а также..? Если вы перебираете все файлы, вы всегда будете видеть записи для. (текущий каталог) и.. (вверх каталог). GetVersion Info вполне может вернуть что-нибудь для них. Вам придется отфильтровать эти записи вручную по имени.