уточняю ответ, предоставленный Тони
Один из проектов в работе имел собственный атрибут, запеченный в этом разделе ресурсов. На 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');