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 вполне может вернуть что-нибудь для них. Вам придется отфильтровать эти записи вручную по имени.

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