Чтение версии исполняемых и мультимедийных файлов с помощью PHP

Раздел: PHP -> Информация о файле

Основные подходы к получению версии файла

Как получить версию файла на Windows с помощью встроенных утилит?

Наиболее простым и эффективным решением является запуск PowerShell через функцию exec() или shell_exec(). Команда Get-Item возвращает объект файла, свойство VersionInfo.FileVersion содержит строку версии.

<?php
$file = 'C:/Windows/System32/notepad.exe';
$cmd = 'powershell -Command \"(Get-Item ' . $file . ').VersionInfo.FileVersion\"';
$version = trim(shell_exec($cmd));
echo $version; // выведет, например, 10.0.19041.1
?>

Php file version (получение версии файла в php)

Объяснение шагов: формирование команды с конкатенацией пути, выполнение, удаление лишних пробелов. Команда работает на любой версии Windows с PowerShell.

Типичные проблемы:

  • Путь к файлу содержит пробелы или спецсимволы. Рекомендация: экранировать путь с помощью функции escapeshellarg().
  • Функция shell_exec() отключена на сервере. Рекомендация: использовать exec() с захватом вывода.
  • Отсутствие PowerShell (например, в старых версиях Windows). Рекомендация: применять альтернативные методы (COM или бинарный разбор).

Каким образом извлечь версию файла через COM-объект?

Для Windows можно использовать объект Shell.Application. Этот способ не требует вызова внешних процессов, но зависит от наличия COM-поддержки в PHP.

<?php
$path = 'C:/Windows/System32/calc.exe';
$shell = new COM('Shell.Application');
$folder = $shell->Namespace(dirname($path));
$file = $folder->ParseName(basename($path));
$version = $folder->GetDetailsOf($file, 27); // 27 - индекс поля "Версия"
echo $version;
?>

Индекс 27 соответствует колонке "Версия файла" в проводнике. Индексы могут отличаться в разных версиях Windows. Рекомендуется вывести все детали для поиска нужного индекса.

Ошибки: COM-расширение может быть отключено в php.ini. Рекомендация: включить extension=php_com_dotnet.dll. Файл может быть недоступен (ошибка прав). Также свойство может не существовать для некоторых типов файлов.

Как прочитать версию из бинарного PE-заголовка?

Для исполняемых файлов Windows версия хранится в ресурсной секции. Можно прочитать бинарный файл и извлечь структуру VS_FIXEDFILEINFO. Это сложный, но кроссплатформенный метод (работает на Linux при чтении .exe).

<?php
// Упрощённый вариант: поиск сигнатуры "VS_VERSION_INFO"
$data = file_get_contents($file);
$pos = strpos($data, 'VS_VERSION_INFO');
if ($pos !== false) {
    // извлечение версии после заголовка
}
?>

Полный код требует разбора PE-структуры: DOS-заголовок, COFF-заголовок, таблица ресурсов. Рекомендуется использовать готовые библиотеки, например, php-pecl или обёртки.

Сложность реализации, поддержка только 32-битных или 64-битных версий, возможны ошибки при чтении. Рекомендуется внимательно изучить формат PE или использовать готовые решения.

Как получить версию изображения из метаданных?

Некоторые файлы изображений (JPEG, TIFF) содержат версию в EXIF-тегах. Функция exif_read_data() возвращает массив с данными, среди которых может быть ExifVersion или Software.

<?php
$exif = exif_read_data('photo.jpg');
$version = $exif['ExifVersion'] ?? $exif['Software'] ?? 'неизвестно';
echo $version;
?>

Для других форматов (PNG, GIF) чтение метаданных ограничено. Для текстовых документов версия может быть встроена в OLE-потоки (требуется COM или бинарный разбор).

Не у всех изображений есть версия. Функция exif_read_data() требует включенного расширения php_exif. Ошибка при повреждённых метаданных. Рекомендация: проверять наличие тегов и обрабатывать исключения.

Как получить версию PHP-проекта из файла composer.json?

Во многих PHP-проектах версия указывается в корневом файле composer.json. Это простой текстовый разбор без внешних зависимостей.

<?php
$composer = json_decode(file_get_contents('composer.json'), true);
$version = $composer['version'] ?? 'не указана';
echo $version;
?>

Этот метод полезен для получения версии библиотеки или приложения, если она задана разработчиком.

Файл может отсутствовать, быть некорректным JSON или не содержать поле version. Рекомендуется устанавливать версию также другими способами (например, через константу в коде).

Расширенные примеры и практические сценарии

Пример 1. Функция для определения версии файла с автоматическим выбором метода в зависимости от платформы.

Пример
<?php
function getFileVersion($path) {
    if (PHP_OS_FAMILY === 'Windows') {
        // PowerShell метод
        $cmd = 'powershell -Command \"(Get-Item ' . $path . ').VersionInfo.FileVersion\"';
        $ver = trim(shell_exec($cmd));
        if ($ver) return $ver;
        // Попытка через COM
        try {
            $shell = new COM('Shell.Application');
            $folder = $shell->Namespace(dirname($path));
            $file = $folder->ParseName(basename($path));
            return $folder->GetDetailsOf($file, 27);
        } catch (Exception $e) {
            // падение
        }
        return false;
    } else {
        // Linux – для .exe можно попробовать через Wine? или file_get_contents
        // Для мультимедиа – exif
        // Вернём false
        return false;
    }
}
?>
Пример вызова: getFileVersion('C:/Windows/System32/notepad.exe') вернёт "10.0.19041.1"

Пример 2. Кеширование результата с помощью memcached или файла.

Пример
<?php
function getCachedFileVersion($path, $ttl = 3600) {
    $cacheFile = sys_get_temp_dir() . '/file_version_' . md5($path) . '.cache';
    if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $ttl)) {
        return file_get_contents($cacheFile);
    }
    $version = getFileVersion($path);
    file_put_contents($cacheFile, $version);
    return $version;
}
?>
При повторном вызове в течение часа вернёт закешированное значение.

Пример 3. Получение версий всех файлов в директории.

Пример
<?php
$dir = 'C:/Program Files/SomeApp';
$files = glob($dir . '/*.exe');
$versions = [];
foreach ($files as $f) {
    $versions[basename($f)] = getFileVersion($f);
}
print_r($versions);
?>
Array ( [app.exe] => 2.1.0.0 [helper.exe] => 1.0.0.0 )

Пример 4. Чтение версии PE-файла с помощью библиотеки (общий пример).

Пример
<?php
// Если установлен пакет pecl/fileinfo? Нет, но можно использовать phalcon? Лучше показать работу с бинарным потоком.
$handle = fopen('file.exe', 'rb');
// ... сложный разбор ...
?>
Упрощённый пример не приводим, так как полный код занимает много строк.

Пример 5. Обработка ошибок при использовании COM.

Пример
<?php
try {
    $shell = new COM('Shell.Application');
    $folder = $shell->Namespace('C:/Windows');
    $file = $folder->ParseName('notepad.exe');
    if ($file) {
        $version = $folder->GetDetailsOf($file, 27);
        echo 'Версия: ' . $version;
    } else {
        echo 'Файл не найден';
    }
} catch (com_exception $e) {
    echo 'Ошибка COM: ' . $e->getMessage();
}
?>
Выведет "Версия: 10.0.19041.1" или "Ошибка COM: ..."

Пример 6. Использование PowerShell с кодировкой UTF-8 и обработкой длинных путей.

Пример
<?php
$path = 'C:/Program Files (x86)/My App/app.exe';
$escaped = escapeshellarg($path);
$cmd = 'powershell -Command \"(Get-Item ' . $escaped . ').VersionInfo.FileVersion\"';
$version = shell_exec($cmd);
echo trim($version);
?>
Вернёт версию, например, "1.5.0.0"

Получение версии файла в PHP - comments

En
Php file version (php)