Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обход папки с получением версий файлов, и сброс в XML. где смотреть/копать? 
:(
    Опции темы
Rockie
Дата 3.1.2007, 04:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1143
Регистрация: 23.4.2006

Репутация: нет
Всего: 31



Здравствуйте! 

Необходимо создать приложение, которое бы позволяло получить версии dll-ок и exe файлов в дирректории(если нет версии, тогда время создания) и поддиректориях. Какие функции использовать?




--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Softaz
Дата 3.1.2007, 10:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


wasm
**


Профиль
Группа: Участник
Сообщений: 373
Регистрация: 16.1.2006

Репутация: 3
Всего: 16



Вот пример с dll. С exe точно также, только изменишь фильтр
Код

            FileInfo[] fi = new DirectoryInfo("C:\\").GetFiles("*.dll", SearchOption.TopDirectoryOnly);
            foreach (FileInfo f in fi)
            {
                try
                {
                    MessageBox.Show(Assembly.LoadFile(f.FullName).GetName().Version.ToString());
                }
                catch (BadImageFormatException ex)
                {
                    MessageBox.Show("Неправильный формат сборки " + f.FullName + Environment.NewLine + ex.ToString());
                }
                //Если "нет" версии (что значит "нет" - непонятно, то f.LastWriteTime
            }


Этот код "узнает" версии только .NET-овских файлов!

Добавлено @ 10:25 
Предполагается, что
Код

using System.IO;
using System.Reflection;



--------------------
Разочарованный в .NET
PM MAIL WWW   Вверх
mr.DUDA
Дата 3.1.2007, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Держи готовый пример. В настройках проекта (вкладка Application) нужно поставить чекбокс "Allow unsafe code", чтобы работали pointer-ы:
Код
using System;
using System.IO;
using System.Runtime.InteropServices;

class Program
{
    void EnumerateFilesRecursive(DirectoryInfo dir)
    {
        // выводим версии файлов EXE и DLL
        foreach (FileInfo file in dir.GetFiles("*.exe"))
            DumpFileVersionInfo(file.FullName);
        foreach (FileInfo file in dir.GetFiles("*.dll"))
            DumpFileVersionInfo(file.FullName);

        // то же самое для вложенных директорий
        foreach (DirectoryInfo innerDir in dir.GetDirectories())
            EnumerateFilesRecursive(innerDir);
    }

    static void Main()
    {
        new Program().EnumerateFilesRecursive(new DirectoryInfo(@"c:\2"));
    }


    // собственно, то что делает всю работу


    [DllImport("version.dll")]
    static extern bool GetFileVersionInfo(string filename, int handle, int len, IntPtr buffer);

    [DllImport("version.dll")]
    static extern int GetFileVersionInfoSize(string filename, ref int unused);

    [DllImport("version.dll")]
    static extern bool VerQueryValue(IntPtr buffer, string key, ref IntPtr dest, ref int destLen);

    void DumpFileVersionInfo(string path)
    {
        int unused = 0;
        Console.WriteLine("Path: " + path);

        // выделяем буфер для версии
        int verBufSize = GetFileVersionInfoSize(path, ref unused);
        IntPtr verBuf = Marshal.AllocHGlobal(verBufSize);

        // получаем информацию о версии в буфер
        GetFileVersionInfo(path, unused, verBufSize, verBuf);

        // если версии нет, то выводим дату создания
        if (verBuf == IntPtr.Zero)
        {
            FileInfo fi = new FileInfo(path);
            Console.WriteLine("Date Created: " + fi.CreationTime.ToLongDateString());
        }
        else
        {
            // получаем чарсет, использованный в версии
            string strCharset;
            IntPtr value = IntPtr.Zero;
            int valueLen = 0;
            VerQueryValue(verBuf, @"\VarFileInfo\Translation", ref value, ref valueLen);
            unsafe
            {
                int* pCharset = (int*)value.ToPointer();
                int iCharset = ((*pCharset) >> 16) | ((*pCharset & 0xffff) << 16);
                strCharset = "0" + iCharset.ToString("x");
            }

            // выводим какие-то поля из версии
            DumpVersionField(verBuf, "FileVersion", strCharset);
            DumpVersionField(verBuf, "FileDescription", strCharset);
            DumpVersionField(verBuf, "ProductVersion", strCharset);
            DumpVersionField(verBuf, "ProductName", strCharset);
            DumpVersionField(verBuf, "CompanyName", strCharset);
            DumpVersionField(verBuf, "LegalCopyright", strCharset);
            DumpVersionField(verBuf, "PrivateBuild", strCharset);
            DumpVersionField(verBuf, "SpecialBuild", strCharset);

            Marshal.FreeHGlobal(verBuf);
        }

        Console.WriteLine();
    }

    void DumpVersionField(IntPtr verBuf, string key, string strCharset)
    {
        // наконец, получаем то что нужно - версию
        IntPtr value = IntPtr.Zero;
        int valueLen = 0;
        VerQueryValue(verBuf, @"\StringFileInfo\" + strCharset + @"\" + key, ref value, ref valueLen);
        if (value != IntPtr.Zero)
        {
            string fieldValue = Marshal.PtrToStringAnsi(value, valueLen);
            Console.WriteLine(key + ": " + fieldValue);
        }
    }
}



--------------------
user posted image
PM MAIL WWW   Вверх
Rockie
Дата 3.1.2007, 18:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1143
Регистрация: 23.4.2006

Репутация: нет
Всего: 31



Softazmr.DUDA, спасибо большое, мужики! 
Я попозже посмотрю, еще буду доставать вопросами. imho  с первого взгляда - два совершенно разных варианта smile





--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Rockie
Дата 11.1.2007, 14:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1143
Регистрация: 23.4.2006

Репутация: нет
Всего: 31



Softaz, дело в том, что при таком варианте
Код

 FileInfo[] fi = new DirectoryInfo("C:\\").GetFiles("*.dll", SearchOption.TopDirectoryOnly);
            foreach (FileInfo f in fi)
            {
                try
                {
                    MessageBox.Show(Assembly.LoadFile(f.FullName).GetName().Version.ToString());
                }
                catch (BadImageFormatException ex)
                {
                    MessageBox.Show("Неправильный формат сборки " + f.FullName + Environment.NewLine + ex.ToString());
                }
                //Если "нет" версии (что значит "нет" - непонятно, то f.LastWriteTime
            }

сначала происходит считывание инфы о всех файлах, а уже потом вывод на экран. На практике этот процесс оказался слишком долгим(большие дирректории). Как можно завернуть в один цикл считывание инфы и отображение?




--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
mr.DUDA
Дата 11.1.2007, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 110
Всего: 232



Использовать винапи (FindFirstFile / FindNextFile). Я когда-то делал перечислитель файлов, можно юзать его с foreach:
Код
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace FileMind.Common
{
    /// <summary>
    /// Provide enumeration of filesystem entries. May be used
    /// in foreach statement.
    /// </summary>
    public class FilesystemEntriesCollection : IEnumerable<string>
    {
        string _parentPath;
        FileAttributes _entryTypes;

        /// <summary>
        /// Create FilesystemEntriesCollection from given parent path.
        /// </summary>
        /// <param name="parentPath">path to enumerate filesystem entries in</param>
        /// <param name="entryTypes">flags indicate, which types of entries to enumerate
        /// - directories, files or both</param>
        public FilesystemEntriesCollection(string parentPath, FileAttributes entryTypes)
        {
            _parentPath = parentPath;
            _entryTypes = entryTypes;
        }

        public IEnumerator<string> GetEnumerator()
        {
            return new FilesystemEntriesEnumerator(_parentPath, _entryTypes);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    /// <summary>
    /// Implements lazy enumeration of filesystem entries.
    /// DONT FORGET TO DISPOSE. Disposed automatically, if used
    /// in foreach statement.
    /// </summary>
    public class FilesystemEntriesEnumerator : IEnumerator<string>
    {
        #region private data members

        string _parentPath;
        FileAttributes _entryTypes;

        static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
        IntPtr _findHandle = INVALID_HANDLE_VALUE;
        WIN32_FIND_DATA _findData = new WIN32_FIND_DATA();

        #endregion

        #region constructor

        /// <summary>
        /// Create FilesystemEntriesEnumerator from given parent path.
        /// </summary>
        /// <param name="parentPath">path to enumerate filesystem entries in</param>
        /// <param name="entryTypes">flags indicate, which types of entries to enumerate
        /// - directories, files or both</param>
        public FilesystemEntriesEnumerator(string parentPath, FileAttributes entryTypes)
        {
            _entryTypes = entryTypes;
            _parentPath = parentPath;
            if (!_parentPath.EndsWith("\\"))
                _parentPath += "\\";
            if (!_parentPath.EndsWith("*"))
                _parentPath += "*";
        }

        #endregion


        // IEnumerator implementation

        #region Current

        /// <summary>
        /// Returns current path.
        /// </summary>
        public string Current
        {
            get
            {
                return _findData.cFileName;
            }
        }

        /// <summary>
        /// Returns current path.
        /// </summary>
        object System.Collections.IEnumerator.Current
        {
            get
            {
                return _findData.cFileName;
            }
        }

        #endregion

        #region Dispose()

        /// <summary>
        /// Free unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (_findHandle != null)
            {
                FindClose(_findHandle);
                _findHandle = INVALID_HANDLE_VALUE;
                _findData = new WIN32_FIND_DATA();
            }
        }

        #endregion

        #region MoveNext()

        /// <summary>
        /// Move to the next filesystem entry.
        /// </summary>
        /// <returns>false, if enumeration cannot start or fails; dispose enumerator anyway</returns>
        public bool MoveNext()
        {
            if (_findHandle == INVALID_HANDLE_VALUE)
            {
                _findHandle = FindFirstFile(_parentPath, out _findData);
                if (!_SkipCurrentEntry())
                    return true;
            }

            while (FindNextFile(_findHandle, out _findData))
            {
                if (!_SkipCurrentEntry())
                    return true;
            }

            return false;
        }

        #endregion

        #region Reset()

        public void Reset()
        {
            Dispose();
        }

        #endregion


        // etc.

        #region _SkipCurrentEntry()

        /// <summary>
        /// Returns true, if current filesystem entry falls out from
        /// the filter of allowed entries _entryTypes, or is special
        /// directory path "." or "..".
        /// </summary>
        /// <returns></returns>
        bool _SkipCurrentEntry()
        {
            if (_findData.cFileName == "." || _findData.cFileName == ".."
                || (_findData.dwFileAttributes & _entryTypes) == 0)
                return true;
            else
                return false;
        }

        #endregion

        #region P/Invoke stuff

        const int MAX_PATH = 260;
        const int MAX_ALTERNATE = 14;

        [StructLayout(LayoutKind.Sequential)]
        public struct FILETIME
        {
            public uint dwLowDateTime;
            public uint dwHighDateTime;
        };

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct WIN32_FIND_DATA
        {
            public FileAttributes dwFileAttributes;
            public FILETIME ftCreationTime;
            public FILETIME ftLastAccessTime;
            public FILETIME ftLastWriteTime;
            public int nFileSizeHigh;
            public int nFileSizeLow;
            public int dwReserved0;
            public int dwReserved1;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
            public string cFileName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)]
            public string cAlternate;
        }

        [DllImport("kernel32", CharSet = CharSet.Auto)]
        static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

        [DllImport("kernel32", CharSet = CharSet.Auto)]
        static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

        [DllImport("kernel32", CharSet = CharSet.Auto)]
        static extern bool FindClose(IntPtr hFindFile);

        #endregion
    }
}



--------------------
user posted image
PM MAIL WWW   Вверх
kelt
Дата 31.5.2010, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 172
Регистрация: 21.6.2005

Репутация: 1
Всего: 0



Всем привет, а можно тоже присоседиться, я тоже работаю над вопросом получения версии

написал такой код:

Код

using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;

using Ionic.Zip;

namespace EsoSetVersion
{
    public class Win32Imports
    {
        [DllImport("version.dll")]
        public static extern bool GetFileVersionInfo(string sFileName,
              int handle, int size, byte[] infoBuffer);
        [DllImport("version.dll")]
        public static extern int GetFileVersionInfoSize(string sFileName,
              out int handle);

        // The third parameter - "out string pValue" - is automatically
        // marshaled from ANSI to Unicode:
        [DllImport("version.dll")]
        unsafe public static extern bool VerQueryValue(byte[] pBlock,
              string pSubBlock, out string pValue, out uint len);
        
        // This VerQueryValue overload is marked with 'unsafe' because 
        // it uses a short*:
        [DllImport("version.dll")]
        unsafe public static extern bool VerQueryValue(byte[] pBlock,
              string pSubBlock, out short* pValue, out uint len);

        [DllImport("version.dll")]
        unsafe public static extern bool VerQueryValue(byte[] pBlock,
                string pSubBlock, out IntPtr pValue, out uint len);
    }
    
    public partial class frmVersion : Form
    {
        public frmVersion()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBrowser_Click(object sender, EventArgs e)
        {
            ///
            if (dlgBrowser.ShowDialog() == DialogResult.OK)
            {
                ///
                tbBrowser.Text = dlgBrowser.SelectedPath;

                if (dlgBrowser.SelectedPath != "")
                {
                    GetModuleList(dlgBrowser.SelectedPath);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="p"></param>
        private void GetModuleList(string folder)
        {
            DirectoryInfo _directory = new DirectoryInfo(folder);

            foreach (FileInfo _file in _directory.GetFiles())
            {
                ///
                if (Path.GetExtension(_file.Name) != ".ini")
                {
                    string[] _row = { _file.Name, GetIDModule(_file), GetVersionModule(_file)};
                    dgModulesView.Rows.Add(_row);
                }
            }
        }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="_file"></param>
        /// <returns></returns>
        unsafe private string GetVersionModule(FileInfo _file)
        {
            string _versionForm = "";
            string _filePath = dlgBrowser.SelectedPath + "\\" + _file.Name;             

            using (ZipFile _zFile = ZipFile.Read(_filePath))
            {
                ///
                foreach (ZipEntry _zEntry in _zFile)
                {
                    string _fileOutput = "C:\\Temp\\" + _zEntry.FileName;
                    ///
                    if (File.Exists(_fileOutput))
                        File.Delete(_fileOutput);

                    _zEntry.Extract("C:\\Temp");

                    try
                    {
                        ///
                        int handle = 0;
                        int size = Win32Imports.GetFileVersionInfoSize(_fileOutput, out handle);

                        if (size != 0)
                        {
                            byte[] buffer = new byte[size];
                            if (Win32Imports.GetFileVersionInfo(_fileOutput, handle, size, buffer))
                            {
                                ///VS_FIXEDFILEINFO* subBlock;
                                IntPtr subBlock = IntPtr.Zero;
                                uint len = 0;

                                if (Win32Imports.VerQueryValue(buffer, "\\", out subBlock, out len))
                                {
                                    ///
                                    ///_versionForm = subBlock.ToInt64().ToString();
                                    _versionForm = Marshal.ReadInt64(subBlock).ToString(); 
                                }
                            }
                        }
                    }
                    finally
                    {
                        ///
                    }

                    if (File.Exists(_fileOutput))
                        File.Delete(_fileOutput);
                }
            }

            return _versionForm;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_file"></param>
        /// <returns></returns>
        private string GetIDModule(FileInfo _file)
        {
            string _idForm = "";
            string _filePath = dlgBrowser.SelectedPath + "\\" + Path.GetFileNameWithoutExtension(_file.Name) + ".ini";

            using (StreamReader _sReader = new StreamReader(_filePath))
            {
                ///
                String _strFormID = _sReader.ReadToEnd();

                if (_strFormID != String.Empty)
                {
                    ///
                    _strFormID = _strFormID.Substring(_strFormID.IndexOf("ID="), 7);
                    _strFormID = _strFormID.Substring(3, 4);

                    _idForm = _strFormID;
                }
            }

            return _idForm;
        }
    }
}


функция unsafe private string GetVersionModule(FileInfo _file) значение вытаскивает в 64 битном варианте но почему для всех файлов одну и туже версию, может я что то не так делаю?

P.S. отмечу что файлы создавались в Делфи, это откомпилированные пакеты имеющие расширение BPL, в другой программе на Делфи используются как раз функции из version.dll, поэтому я в своем проекте их и решил использовать, чтобы при сравнении версий не было различий

Это сообщение отредактировал(а) kelt - 31.5.2010, 09:56
--------------------
Timeo danaos et dona ferentes 
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0784 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.