FileVersionInfo.GetVersionInfo () неправильно в консольном приложении - PullRequest
4 голосов
/ 08 февраля 2010

Я получаю некоторую серьезную странность с помощью FileVersionInfo.GetVersionInfo () и надеялся, что кто-нибудь сможет помочь.

Основой проблемы является то, что я перебираю все файлы в папке, вызывая GetVersionInfo () для каждого. Есть около 300 файлов. Это работает нормально для всех, кроме 2 файлов. Для этих библиотек я получаю совершенно неверную информацию от GetVersionInfo ().

Чтобы исключить все остальные переменные, я извлек этот вызов в простое тестовое приложение, и у него все еще возникла та же проблема. Однако, если я собрал тестовое приложение как приложение Windows (изначально это было консольное приложение), данные вернулись верными.

Просто чтобы уточнить, неверные данные, возвращающиеся при запуске в качестве консольного приложения, - это не просто нулевая информация, как если бы файл не содержал данных о версии. Это содержало разумные данные, но только неправильные данные. Как будто он читает его из другого файла. Я искал файл, который содержит соответствующие данные о версии, но не могу найти.

Почему этот простой вызов работает по-другому, если он создан как консольное приложение, а не как приложение Windows?

Если кто-нибудь может помочь с этим, я был бы очень признателен.

Rgds, Andy

- Код добавлен

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 ]

8 голосов
/ 10 февраля 2010

Такое поведение действительно кажется странным. Может ли быть так, что консольное приложение не загружает 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 и убедитесь, что для информации о версии существует только одна языковая / кодовая страница. Надеюсь, это поможет вам найти решение.

0 голосов
/ 08 февраля 2010

Версии файлов и сборок - это две разные вещи.

Вы уверены, что не ожидаете другого?

0 голосов
/ 08 февраля 2010

Обновление: пробовал это. Не сработало.

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));
        }
    }
}
0 голосов
/ 08 февраля 2010

Конечно, «файлы», которые вы видите, не являются. а также .. ? Если вы перебираете все файлы, вы всегда будете видеть записи для. (текущий каталог) и .. (вверх каталог). GetVersion Info вполне может вернуть что-нибудь для них. Вам придется отфильтровать эти записи вручную по имени.

...