Intereting Posts
@ символ перед вызовом функции Унаследованные атрибуты Laravel 4 равны нулю Zend Framework 2 – Проверка пользовательской формы взорвать список из двух элементов в массиве в качестве значения ключа => jQuery Connected Sortable Lists, Save Order to MySQL Создание новых данных с помощью функции POST dosen't в laravel 5 Поиск ключей многомерного массива с использованием другого массива Преобразовать серию отношений родитель-ребенок в иерархическое дерево? как перечислить переменную массива, созданную с помощью рекурсивной функции в Smarty Запуск __call () в PHP, даже когда существует метод Проблема обработки массива textareas, когда они динамически загружаются с помощью jQuery и PHP Цепочки методов PHP – Отражение? MYSQL Query – получать сообщения текущего пользователя, а пользователь – следующие сообщения Laravel – подзапрос с использованием Query Builder API-интерфейс Foursquare для ошибки изображения пользователя сайта

Получить версию exe через PHP

Получается ли версия exe с php? Я хотел бы распечатать версию файла, который можно скачать …

Windows exe и php работают на сервере linux

Я хотел получить то же самое, поэтому я закодировал это: он возвращает FALSE, если он не может получить информацию о версии, или ARRAY из четырех элементов с полями версии файла (числа, которые разделены.) Он работает только для 32- битных файлов PE (так как мне не нужны были другие форматы).

function GetFileVersion($FileName) { $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1]<64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) { //$x fixed here $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') { //resource section $ResFound=TRUE; break; } } if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,14,2)); $InfoFound=FALSE; for ($x=0;$x<$NumDirs[1];$x++) { $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) { //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); break; } } if (!$InfoFound) return FALSE; $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; } 

На машине win32 вы можете использовать расширение COM и метод FileSystemObject.GetFileVersion () для получения информации о версии. например

 $path = getenv('SystemRoot').'\\NOTEPAD.EXE'; $fso = new COM('Scripting.FileSystemObject'); echo $path, ' : ', $fso->GetFileVersion($path); 

(на моей машине) C:\WINDOWS\NOTEPAD.EXE : 5.1.2600.5512

Недавно я перенес наш хостинг из Windows в Linux. Это было довольно легко сделать с VBScript с учетом объектов Microsoft, но в Linux и PHP я ничего не мог найти. Мы написали эту функцию в PHP, чтобы отсканировать файл .exe и извлечь «Версию продукта», в которой было приложение VB.Net. Вы можете изменить ключ $, чтобы быть любой строкой, которую вы можете найти с информацией о версии и нулевым терминатором.

Обратите внимание, что это сканирует файлы в 64k кусках, ища строку $ key. Если у вас большой .exe, это может занять несколько секунд. Мой .exe – 52k, так что это почти мгновенно. Если у вас больше EXE, вы можете изменить сканирование.

 <?php function get_product_version($file_name) { $key = "P\x00r\x00o\x00d\x00u\x00c\x00t\x00V\x00e\x00r\x00s\x00i\x00o\x00n\x00\x00\x00"; $fptr = fopen($file_name, "rb"); $data = ""; while (!feof($fptr)) { $data .= fread($fptr, 65536); if (strpos($data, $key)!==FALSE) break; $data = substr($data, strlen($data)-strlen($key)); } fclose($fptr); if (strpos($data, $key)===FALSE) return ""; $pos = strpos($data, $key)+strlen($key); $version = ""; for ($i=$pos; $data[$i]!="\x00"; $i+=2) $version .= $data[$i]; return $version; } echo get_product_version("/path_to_file/foo.exe"); ?> 

Я предполагаю, что вы не в Windows, и вы имеете в виду информацию о версии, которая может быть сохранена в исполняемых файлах Windows, и появляется в диалоговом окне свойств для такого файла в проводнике Windows.

Эта информация, похоже, хранится в блоке VS_VERSION_INFO исполняемого файла (см., Например, этот вопрос ). Я не знаю никакого инструмента, который извлекает эту информацию простым способом, даже не в самой Windows.

Кажется, есть несколько способов получить эту информацию через Windows API (см. Пример Perl здесь ), но я не вижу никакого подхода, который работает «с нуля», просто анализируя исполняемый файл.

Если вы копаете немного, вы можете найти описание формата файла, которое объясняет, как читать информацию VS_VERSION_INFO из EXE-файла. Будьте готовы к большой работе, чтобы заставить это работать надежно.

Будьте готовы потратить много времени и усилий, если вы хотите это сделать.

Выработка ответа на вопрос Тони. Один из проектов на рабочем месте имел специальный атрибут, запеченный в этой секции ресурсов. На машине linux мы не хотели устанавливать perl для использования функции windows для получения значений. Вместо этого можно использовать этот вариант GetFileVersion для получения любого значения, которое вы ищете. (FileVersion, ProductVersion, ProductName, CompanyName, CompanyWebsite) Он должен возвращать false для значений, которые не существуют, и он функционирует довольно быстро.

  $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1]<64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) { $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') { //resource section $ResFound=TRUE; break; } } if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,14,2)); $InfoFound=FALSE; for ($x=0;$x<$NumDirs[1];$x++) { $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) { //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); //echo $Info; break; } } if (!$InfoFound) return FALSE; // i bypassed this, but if you knew the layout you could prolly do a little better then $ulgyRemainderOfData /* $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); // swap 1-2 3-4 / endian ecoding issue $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; */ //view data... //echo print_r(explode("\x00\x00\x00", $Info)); // could prolly substr on VS_VERSION_INFO $encodedKey = implode("\x00",str_split($seeking)); $StartOfSeekingKey = strpos($Info, $encodedKey); if ($StartOfSeekingKey !== false) { $ulgyRemainderOfData = substr($Info, $StartOfSeekingKey); $ArrayOfValues = explode("\x00\x00\x00", $ulgyRemainderOfData); // the key your are seeking is 0, where the value is one return trim($ArrayOfValues[1]); } return false; } $fileVersion = GetValueOfSeeking("./the/path/to/some.exe", 'FileVersion'); $myAttribute = GetValueOfSeeking("./the/path/to/some.exe", 'CustomAttribute'); 

Для меня, чтобы получить код от Тони для работы, мне пришлось сделать небольшое изменение:

 function GetFileVersion($FileName) { $handle=fopen($FileName,'rb'); if (!$handle) return FALSE; $Header=fread ($handle,64); if (substr($Header,0,2)!='MZ') return FALSE; $PEOffset=unpack("V",substr($Header,60,4)); if ($PEOffset[1]<64) return FALSE; fseek($handle,$PEOffset[1],SEEK_SET); $Header=fread ($handle,24); if (substr($Header,0,2)!='PE') return FALSE; $Machine=unpack("v",substr($Header,4,2)); if ($Machine[1]!=332) return FALSE; $NoSections=unpack("v",substr($Header,6,2)); $OptHdrSize=unpack("v",substr($Header,20,2)); fseek($handle,$OptHdrSize[1],SEEK_CUR); $ResFound=FALSE; for ($x=0;$x<$NoSections[1];$x++) { //$x fixed here $SecHdr=fread($handle,40); if (substr($SecHdr,0,5)=='.rsrc') { //resource section $ResFound=TRUE; break; } } if (!$ResFound) return FALSE; $InfoVirt=unpack("V",substr($SecHdr,12,4)); $InfoSize=unpack("V",substr($SecHdr,16,4)); $InfoOff=unpack("V",substr($SecHdr,20,4)); fseek($handle,$InfoOff[1],SEEK_SET); $Info=fread($handle,$InfoSize[1]); $NumDirs=unpack("v",substr($Info,16,2)); $InfoFound=FALSE; for ($x=0;$x<$NumDirs[1];$x++) { $Type=unpack("V",substr($Info,($x*8)+16,4)); if($Type[1]==16) { //FILEINFO resource $InfoFound=TRUE; $SubOff=unpack("V",substr($Info,($x*8)+20,4)); break; } } if (!$InfoFound) return FALSE; $SubOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$SubOff[1]+20,4)); //offset of first FILEINFO $InfoOff[1]&=0x7fffffff; $InfoOff=unpack("V",substr($Info,$InfoOff[1]+20,4)); //offset to data $DataOff=unpack("V",substr($Info,$InfoOff[1],4)); $DataSize=unpack("V",substr($Info,$InfoOff[1]+4,4)); $CodePage=unpack("V",substr($Info,$InfoOff[1]+8,4)); $DataOff[1]-=$InfoVirt[1]; $Version=unpack("v4",substr($Info,$DataOff[1]+48,8)); $x=$Version[2]; $Version[2]=$Version[1]; $Version[1]=$x; $x=$Version[4]; $Version[4]=$Version[3]; $Version[3]=$x; return $Version; } 

Где я только изменил 14 – 16 в строке

 $NumDirs=unpack("v",substr($Info,16,2)); 

Возможно, это имеет какое-то отношение к тому, что j_schultz уже добавил в комментариях.

Я объединил ответы вместе и добавил исправление NamedDirs. Также хочу подчеркнуть, что не использовать код NeuD, смещение должно оставаться 16; 14 определенно неверно. Надеюсь, это поможет кому-то.

 function GetFileVersion($FileName) { return GetValueOfSeeking($FileName, "FileVersion"); } function GetValueOfSeeking($FileName, $seeking) { $handle = fopen($FileName, 'rb'); if (!$handle) return FALSE; $Header = fread($handle, 64); if (substr($Header, 0, 2) != 'MZ') return FALSE; $PEOffset = unpack("V", substr($Header, 60, 4)); if ($PEOffset[1]<64) return FALSE; fseek($handle, $PEOffset[1], SEEK_SET); $Header = fread ($handle, 24); if (substr($Header, 0, 2) != 'PE') return FALSE; $Machine = unpack("v", substr($Header, 4, 2)); if ($Machine[1] != 332) return FALSE; $NoSections = unpack("v", substr($Header, 6, 2)); $OptHdrSize = unpack("v", substr($Header, 20, 2)); fseek($handle, $OptHdrSize[1], SEEK_CUR); $ResFound = FALSE; for ($x = 0; $x < $NoSections[1]; $x++) { //$x fixed here $SecHdr = fread($handle, 40); if (substr($SecHdr, 0, 5) == '.rsrc') { //resource section $ResFound = TRUE; break; } } if (!$ResFound) return FALSE; $InfoVirt = unpack("V", substr($SecHdr, 12, 4)); $InfoSize = unpack("V", substr($SecHdr, 16, 4)); $InfoOff = unpack("V", substr($SecHdr, 20, 4)); fseek($handle, $InfoOff[1], SEEK_SET); $Info = fread($handle, $InfoSize[1]); $NumNamedDirs = unpack("v",substr($Info, 12, 2)); $NumDirs = unpack("v", substr($Info, 14, 2)); $InfoFound = FALSE; for ($x = 0; $x < ($NumDirs[1] + $NumNamedDirs[1]); $x++) { $Type = unpack("V", substr($Info, ($x * 8) + 16, 4)); if($Type[1] == 16) { //FILEINFO resource $InfoFound = TRUE; $SubOff = unpack("V", substr($Info, ($x * 8) + 20, 4)); break; } } if (!$InfoFound) return FALSE; if (0) { $SubOff[1] &= 0x7fffffff; $InfoOff = unpack("V", substr($Info, $SubOff[1] + 20, 4)); //offset of first FILEINFO $InfoOff[1] &= 0x7fffffff; $InfoOff = unpack("V", substr($Info, $InfoOff[1] + 20, 4)); //offset to data $DataOff = unpack("V", substr($Info, $InfoOff[1], 4)); $DataSize = unpack("V", substr($Info, $InfoOff[1] + 4, 4)); $CodePage = unpack("V", substr($Info, $InfoOff[1] + 8, 4)); $DataOff[1] -= $InfoVirt[1]; $Version = unpack("v4", substr($Info, $DataOff[1] + 48, 8)); $x = $Version[2]; $Version[2] = $Version[1]; $Version[1] = $x; $x = $Version[4]; $Version[4] = $Version[3]; $Version[3] = $x; return $Version; } //view data... //echo print_r(explode("\x00\x00\x00", $Info)); // could prolly substr on VS_VERSION_INFO $encodedKey = implode("\x00",str_split($seeking)); $StartOfSeekingKey = strpos($Info, $encodedKey); if ($StartOfSeekingKey !== false) { $ulgyRemainderOfData = substr($Info, $StartOfSeekingKey); $ArrayOfValues = explode("\x00\x00\x00", $ulgyRemainderOfData); // the key your are seeking is 0, where the value is one return trim($ArrayOfValues[1]); } return false; }