Win32 Version Control by Ping Ni and Mark Nelson Listing One ############################################################################ # This program will change the FileVersion and FILEVERSION accordingly and # set them consistently across all the directories. # To use this program, run as # IncVersion.pl major project-1 project-2 ... # or # IncVersion.pl minor project-1 project-2 ... # The version info will be used to generate label.bat that can be call to # label files in SourceSafe. ############################################################################# $maxMajor = 0; $maxMinor = 0; $count = 1; # find the max of major and minor version number while ($count <= $#ARGV) { $file1 = $ARGV[$count]."\\".$ARGV[$count].".rc"; eval { SetMax() }; print $@; $count++; } if ($ARGV[0] eq "major") { $maxMajor++; $maxMinor = 0; } else { $maxMinor++; } # write a batch file to be called later to set labels in SourceSafe $labelFile = "label.bat"; open(OutLabel, ">$labelFile") || die "Failed to open $labelFile to write\n\t$!\n"; print OutLabel "ss label -C- -L\"PROJECT $maxMajor\.$maxMinor\"\n"; close(OutLabel); $count = 1; while ($count <= $#ARGV) { $file1 = $ARGV[$count]."\\".$ARGV[$count].".rc"; $file2 = $ARGV[$count]."\\".$ARGV[$count].".tmp"; eval { ProcessFile()}; if ($@) { print $@; } else { eval { CopyFile()}; print $@; } $count++; } sub SetMax { print "Find the max in $file1\n"; open(InRC, "$file1") || die "Failed to open $file1 to read\n\t$!\n"; while ($_ = ) { if ($_ =~/FILEVERSION/) { @currentLine = split(' ', $_); @oldVersion = split(',', $currentLine[1]); if ($oldVersion[0] > $maxMajor) { $maxMajor = $oldVersion[0]; } if ($oldVersion[2] > $maxMinor) { $maxMinor = $oldVersion[2]; } } elsif ($_ =~/FileVersion/) { @currentLine = split(' ', $_); @item = split('"', @currentLine[2]); @vItem = split(/\\/, @item[1]); @version = split('\.', $vItem[0]); if ($version[0] > $maxMajor) { $maxMajor = $version[0]; } if ($version[1] > $maxMinor) { $maxMinor = $version[1]; } } } close (InRC); } sub ProcessFile { print "Converting $file1 to $file2\n"; open(InRC, "$file1") || die "Failed to open $file1 to read\n\t$!\n"; open(OutRC, ">$file2") || die "Failed to open $file2 to write\n\t$!\n"; while ($_ = ) { if ($_ =~/FILEVERSION/) { print OutRC " FILEVERSION $maxMajor,0,$maxMinor,0\n"; } elsif ($_ =~/FileVersion/) { print OutRC "\t VALUE \"FileVersion\", \"$maxMajor.$maxMinor\\0\"\n"; } else { print OutRC "$_"; } } close (InRC); close (outRC); } sub CopyFile { print "Copying $file2 to $file1\n"; unlink($file1); open(InRC, "$file2") || die "Failed to open $file2 to read\n\t$!\n"; open(OutRC, ">$file1") || die "Failed to open $file1 to write\n\t$!\n"; while ($_ = ) { print OutRC "$_"; } close (InRC); close (outRC); } Listing Two #include #include using namespace std; // Extracts the fixed-info version information from the version resource in // the RC file for the current module. The four integers that make up the // fixed-info version information are formatted into a string and returned // to the caller. string FixedModuleVersion() { char file_name[ MAX_PATH ]; GetModuleFileName( ::GetModuleHandle( NULL ), file_name, MAX_PATH ); DWORD dwDummyHandle; DWORD len = GetFileVersionInfoSize( file_name, &dwDummyHandle ); vector buf( len ); ::GetFileVersionInfo( file_name, 0, len, buf.begin() ); unsigned int ver_length; LPVOID lpvi; ::VerQueryValue( buf.begin(), "\\", &lpvi, &ver_length ); VS_FIXEDFILEINFO fileInfo; fileInfo = *(VS_FIXEDFILEINFO*)lpvi; stringstream s; s << HIWORD(fileInfo.dwFileVersionMS) << "." << LOWORD(fileInfo.dwFileVersionMS) << "." << HIWORD(fileInfo.dwFileVersionLS) << "." << LOWORD(fileInfo.dwFileVersionLS); return s.str(); } // This routine will extract the version string from the string version // resource in the RC file for the current module. You must add version.lib // to your project to link to the Win32 versioning API calls. The actual call // VerQueryValue() uses a value of 040904B0 for the language and character set. // This value is equivalent to English language text encoded using Unicode. // string StringModuleVersion() { char file_name[ MAX_PATH ]; GetModuleFileName( ::GetModuleHandle( NULL ), file_name, MAX_PATH ); DWORD dwDummyHandle; DWORD len = GetFileVersionInfoSize( file_name, &dwDummyHandle ); vector buf( len ); ::GetFileVersionInfo( file_name, 0, len, buf.begin() ); char *version; unsigned int ver_length; ::VerQueryValue( buf.begin(), "\\StringFileInfo\\040904B0\\FileVersion", (void **) &version, &ver_length ); return string( version, ver_length ); } 3