This is an effort to write filever.exe in Perl. Filever extracts file version information and is available in the later Windows resource kits I think, or maybe as early as NT4. In verbose mode it prints info like this:
D:\>filever.exe /v c:\windows\system32\kernel32.dll --a-- W32i DLL ENU 5.1.2600.0 shp 926,720 08-23-2001 kernel32.dll Language 0x0409 (English (United States)) CharSet 0x04b0 Unicode OleSelfRegister Disabled CompanyName Microsoft Corporation FileDescription Windows NT BASE API Client DLL InternalName kernel32 OriginalFilenam kernel32 ProductName Microsoft« Windows« Operating System ProductVersion 5.1.2600.0 FileVersion 5.1.2600.0 (xpclient.010817-1148) LegalCopyright ⌐ Microsoft Corporation. All rights reserved. VS_FIXEDFILEINFO: Signature: feef04bd Struc Ver: 00010000 FileVer: 00050001:0a280000 (5.1:2600.0) ProdVer: 00050001:0a280000 (5.1:2600.0) FlagMask: 0000003f Flags: 00000000 OS: 00040004 NT Win32 FileType: 00000002 Dll SubType: 00000000 FileDate: 00000000:00000000 I want to do the same thing with Perl so my script can use the information without having to rely on an external exe, and I don't want to use AdminMisc (I forget why right now, maybe pride or something even dummer). The script below prints: c:\windows\system32\kernel32.dll î♥4 VS_VERSION_INFO ╜♦∩■ ♣ ( ♣ ( ? ♦♦☻ Ω☻ StringFileInfo ╞☻ 040904B0 L▬ CompanyName Microsoft Corporation f▼ FileDescription Windows NT BASE API Client DLL d" FileVersion 5.1.2600.0 (xpclient.010817-1148) 2 InternalName kernel32 Ç. LegalCopyright ⌐ Microsoft Corporation. All rights reserved. : OriginalFilename kernel32 j% ProductName Microsoft« Windows« Operating System :♂ ProductVersion 5.1.2600.0 D VarFileInfo $♦ Translation ♦░♦FE2X [Screen capture if that doesn't make any sense: http://www.eskimo.com/~ghawk/images/filever.gif] Now, most everything in there is relatively easy to clean up. The problem area is the information between VS_VERSION_INFO and StringFileInfo that if translated to hex will become the numbers shown by filever.exe in the VS_FIXEDFILEINFO section. So if you do a match between the two bookends and then unpack("h*", $&), you get a hex string with all of the data. In an ideal world. It works fine on some files. Drop the first ten bytes and then from that point some of them need to be reversed but it is accurate. Here's the problem: With that particular dll the VS_VERSION_INFO contains "00050001:0a280000". Somehow, when the pattern match sees 0a (really a0 because it has to be reversed later, or possibly 000A (a Unicode linefeed, since the \000's are still in there at that point), it interprets that as '\n', and the screen print does too, as you can see above. I want it all on one line or least be able to match past those. I tried $/ = "", $/ = "xyz", and $* = 1 to no avail. Is there someone out there, some Unicode guru or anybody who can help clear up what's wrong here? My Perl version is v5.6.1 built for MSWin32-x86-multi-thread. Thanks! Gary #!perl.exe use Win32::API; #use utf8; # no effect if (! $ARGV[0]) { print "\n\tFilename arg needed.\n\n"; exit; } else { $filename = $ARGV[0]; } if ($filename && $filename =~ /\*/) { # for *.* etc wildcards $filenameprefix = $filename; $filenameprefix =~ s/(.*)\\.*/$1\\/; @filenames = `dir /b $filename`; # readdir later maybe } else { $filenames[0] = $filename; } chomp @filenames; for (@filenames) { s/^(.*)/$filenameprefix$1/; # reassemble full path $pBlock = ""; print "\n\n$_\t\n\n"; $GetFileVersionInfoSize = new Win32::API( "version.dll", "GetFileVersionInfoSizeA", ['P', 'P'], 'N' ); if ( $GetFileVersionInfoSize->Call( $_, $lpHandle ) ) { $lpBufferSize = $GetFileVersionInfoSize->Call( $_, $lpHandle ); } else { print "Apparently 16-bit\n"; next; } $GetFileVersionInfo = new Win32::API( "version.dll", "GetFileVersionInfoA", ['P', 'N', 'N', 'P'], 'I' ); $pBlock = "#" x $lpBufferSize; if ( $GetFileVersionInfo->Call( $_, 0, $lpBufferSize, $pBlock ) ) { $one_or_zero_ignored = $GetFileVersionInfo->Call( $_, 0, $lpBufferSize, $pBlock ); # merely to get $pBlock } $lplpBuffer = "X" x 32; $puLen = 16; $VerQueryValue = new Win32::API( "version.dll", "VerQueryValueA", ['P', 'P' , 'P', 'P'], 'N' ); if (! $VerQueryValue->Call( $pBlock, $lpSubBlock, $lplpBuffer, $puLen ) ) { print Win32::FormatMessage(Win32::GetLastError); } #print "$pBlock\n"; next; # raw output, or... $pBlock =~ s/\#*$//; # excess buffer erase $pBlock =~ s/\001\000/\n/g; # 001 smiley face, \000 space $pBlock =~ s/\000\000\000/\t/g; # mo pretty $pBlock =~ s/\000//g; # human-readable print "$pBlock\n"; } __END__ -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]