Microsoft Visual C++ 6 (VC6) 是個歷史悠久的 compiler,自 1998 年推出之後,一直到了 2002 年,才有 Visual Studio .NET 2002 這個後繼版本推出。在這期間,Microsoft 一共推出了 6 個 service packs,以解決各種 VC6 的 bug。但在實務上,我們並沒有一個很方便的方法,可以得知目前灌在系統裡的 VC6,其 service pack 的版本為何:

  • 從 VC6 選單的 Help > About Visual C++,我們只會看到簡單的「Visual C++R 6.0」的版本號。
  • 從控制台的「變更或移除程式」,我們也只能看到「Microsoft Visual Studio 6.0 xxx Edition」的字樣。

能否弄清楚 patch 到那一版的 service pack,有時候非常重要。不同的 service pack 版本,小則編譯出來的程式執行效率不同,大則執行結果不同,這些差異,無法忽視。

根據 MSDN 的這篇《How To Tell That a Visual Studio Service Pack Is Installed》的說法,並沒有什麼快速方便的方法[1],可以知道目前系統裡安裝的 VC6 service pack 版本,只能夠藉著查詢各個相關 DLL 的版本,反推回 service pack 版號。所以,我們必須先收集好,各個 service pack 版本裡的幾個重要 DLL 的版本號碼,以便之後可以對照查找,辨認出 service pack 的版號。

因為這實在是很麻煩,所以我就寫了一個 script,把表建進去,這樣以後就不用這麼辛苦:

#!/usr/bin/perl -w

use File::Spec::Functions;
use Data::Dump qw(dump);

sub file_version
{
    my $file = shift or die;
    use Win32::File::VersionInfo;
    my $vinfo = GetFileVersionInfo($file);
    if ($vinfo) {
        return $vinfo->{'FileVersion'};
    }
    return undef;
}

my $vc6_dir = catfile($ENV{'ProgramFiles'}, 'Microsoft Visual Studio', 'VC98');
my $vc6_versions = {
    ....
    'vc6-sp5' => {
        catfile($vc6_dir, 'Bin', 'C1.DLL')     => '12.0.8867.0',
        catfile($vc6_dir, 'Bin', 'C1XX.DLL')   => '12.0.8961.0',
        catfile($vc6_dir, 'Bin', 'CL.EXE')     => '12.0.8804.0',
        catfile($vc6_dir, 'Bin', 'LINK.EXE')   =>  '6.0.8447.0',
        catfile($vc6_dir, 'Bin', 'CVTRES.EXE') =>  '5.0.1736.1',
    },
    'vc6-sp6' => {
        catfile($vc6_dir, 'Bin', 'C1.DLL')     => '12.0.9782.0',
        catfile($vc6_dir, 'Bin', 'C1XX.DLL')   => '12.0.9782.0',
        catfile($vc6_dir, 'Bin', 'CL.EXE')     => '12.0.8804.0',
        catfile($vc6_dir, 'Bin', 'LINK.EXE')   =>  '6.0.8447.0',
        catfile($vc6_dir, 'Bin', 'CVTRES.EXE') =>  '5.0.1736.1',
    },
};

foreach my $version (sort keys %$vc6_versions) {
    my $is_this_version = 1;
    foreach my $file (sort keys %{$vc6_versions->{$version}}) {
        my $fv = file_version($file);
        if (!defined($fv)) {
            $is_this_version = 0;
            last; # foreach ($file)
        }
        if ($fv ne $vc6_versions->{$version}->{$file}) {
            $is_this_version = 0;
            last; # foreach ($file)
        }
    }
    if ($is_this_version) {
        print "$version\n";
        exit;
    }
}
print "vc6\n";

可是,如果只是單純為了在同事的電腦裡跑這隻 perl script,還要在同事的電腦裡裝一整套 perl 以及 File::SpecWin32::File::VersionInfo 等套件,那實在是太辛苦了,也不切實際。所以我就又找了 perl2exe 這隻程式,幫我把上面的 script 轉成一個單獨的 EXE 執行檔[2],這樣就可以到處確認大家電腦裡灌的 VC6 的版本有沒有統一了。


  1. 嘆,就算是有個 registry entry 可以查也好。
  2. 雖然據說 perl2exe 有一些問題,但對於這支小程式來說,剛剛好夠用,也沒有發生問題。