Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / ATL

Microsoft Visual Studio Solution File Version Changer

Rate me:
Please Sign up or sign in to vote.
4.95/5 (16 votes)
18 Apr 2010CPOL2 min read 97.9K   4K   59   14
Microsoft Visual Studio Solution File Version Changer - for Visual Studio versions 2002, 2003, 2005, 2008 and 2010

Introduction

This project is a Windows Explorer Shell Extension (right mouse menu) for quickly changing the version of a Visual Studio Solution File. The project source shows you how to create a Explorer Shell Extension and how to convert between the solution versions. The basis for this Shell Extension is Michael Dunn's The Complete Idiot's Guide to Writing Shell Extensions - Part II.

Shot_ContextMenu_v1.0.0.2.png

Visual Studio Solution File Versions

Here you have an overview of the Visual Studio Versions with the File and Product Versions as it might be a little confusing seeing through all the different versions involved.

Visual Studio VersionFile VersionProduct Version
Microsoft Visual Studio .NET (2002)7.007
Visual Studio 20038.007.1
Visual Studio 20059.008
Visual Studio 200810.009
Visual Studio 201011.00 10

Solution File Version 8.00

Till version 8.00, all you need to change is the version number on the second line in the *.sln file:

2003_file.png

Solution File Version 9.00

In version 9.00 and above, you have to change the second line as well as the third:

2005_file.png

Using the Code

A VC++ project compiled with Visual Studio .NET 2008 but also can be compiled with VS2003. It's an ATL ComObject which has to be registered with regsvr32. The code shows you how to:

  • Create self registering COM Object with ATL
  • Convert Microsoft VS *.sln files between versions
  • Create submenus with icon in Explorer context menu

First we analyze the version and save the original file to an internal structure (vector of string):

C++
SlnVersions CVersionChanger::AnalyzeFileVersion(const string_list* pFileList) {
    m_pFileList = pFileList;
    SlnVersions slnFoundVersion = SlnVersions::NA;

    int nSize = m_pFileList->size();
    vector< vector<string>> v_arr(nSize);
    vector<int> v_lines;
    vector<double> v_versions;

    int filePos = 0;    

    for ( string_list::const_iterator it = m_pFileList->begin(); 
	it != m_pFileList->end(); it++ ){
        ifstream ifs(it->c_str());
        string temp; 
        int linePos = 0;
        bool lineFound = false;

        while(getline(ifs, temp )){
            v_arr[filePos].push_back(temp);
            const char* sTmpLine = strstr(temp.c_str(), FORMAT_VERSION_TAG);
            if(sTmpLine != 0){
                v_lines.push_back(linePos);
                string sLine = temp.c_str();
                string str2 = sLine.substr(strlen(FORMAT_VERSION_TAG)+1, 
		sLine.length() - strlen(FORMAT_VERSION_TAG)-1);
                double dVar = 0;
                dVar = atof(str2.c_str()); 
                v_versions.push_back(dVar);
                switch((int)dVar){
                    case 11:
			slnFoundVersion = SlnVersions::eleven;
			break;
                    case 10:
                        slnFoundVersion = SlnVersions::ten;
                        break;
                    case 9:
                        slnFoundVersion = SlnVersions::nine;
                        break;
                    case 8:
                        slnFoundVersion = SlnVersions::eight;
                        break;
                    case 7:
                        slnFoundVersion = SlnVersions::seven;
                        break;
                    default:
                        slnFoundVersion = SlnVersions::NA;
                }
                v_slnVersions.push_back((int)slnFoundVersion);
                lineFound = true;
            }
            linePos++;
        }
        if(!lineFound)
            v_lines.push_back(-1);

        ifs.close();
        filePos++;
    } 
    v_lineContent  = v_arr;
    v_linePos = v_lines;
    v_fileVersions = v_versions;
    return slnFoundVersion;
    }

With the following function, we can convert the file(s) to any version we need.

C++
void CVersionChanger::ChangeVersion(SlnVersions slnChangeTo){
    int nCounter = 0;
    for ( string_list::const_iterator it = m_pFileList->begin(); 
		it != m_pFileList->end(); it++ ) {
        
        
        if(cfgMgr.bBackup)
            ff.CreateBakFile(it->c_str(), cfgMgr.sBakExt);

        string sTmpExt = cfgMgr.sNewExt;
        string sTmpOut = it->c_str();

        if(!cfgMgr.bOverwrite)
            sTmpOut = sTmpOut + sTmpExt;

        ofstream outputFile(sTmpOut.c_str());

            //As long as output file is open...
        if(outputFile.is_open())
        {
            for(int i = 0; i < v_lineContent[nCounter].size(); i++){
                //And then write out all that was read
                string sOut = "";
                int nOutLen = 0;
                if(i == v_linePos.at(nCounter)){
                    char* sTmpOutput = new char[strlen(FORMAT_VERSION_TAG) + 
				(v_fileVersions.at(nCounter)>= 10 ? 4 : 3) + 2];
                    sprintf(sTmpOutput, "%s %i.00\n", FORMAT_VERSION_TAG,  
				(int)slnChangeTo);
                    sOut = sTmpOutput;
                    nOutLen = strlen(sTmpOutput);
                }else{
                    sOut = v_lineContent[nCounter].at(i) + "\n";
                    nOutLen = v_lineContent[nCounter].at(i).length()+1;
                }
                outputFile.write((char*)sOut.c_str(), nOutLen);
                if(i == v_linePos.at(nCounter)){
                   if(slnChangeTo == SlnVersions::eleven){
			outputFile.write(VS2010, strlen(VS2010));
			if(v_fileVersions.at(nCounter) != 
			(int)SlnVersions::eight | v_fileVersions.at(nCounter) != 
			(int)SlnVersions::seven)
		            i++;
                   }else if(slnChangeTo == SlnVersions::ten){
                        outputFile.write(VS2008, strlen(VS2008));
                        if(v_fileVersions.at(nCounter) != 
			(int)SlnVersions::eight | v_fileVersions.at(nCounter) != 
			(int)SlnVersions::seven)
                            i++;
                    }else if(slnChangeTo == SlnVersions::nine){
                        outputFile.write(VS2005, strlen(VS2005));
                        if(v_fileVersions.at(nCounter) != 
			(int)SlnVersions::eight | v_fileVersions.at(nCounter) != 
			(int)SlnVersions::seven)
                            i++;
                    }else if(slnChangeTo == SlnVersions::eight){
                        if(v_fileVersions.at(nCounter) != 
			(int)SlnVersions::eight | v_fileVersions.at(nCounter) != 
			(int)SlnVersions::seven)
                            i++;
                    }else if(slnChangeTo == SlnVersions::seven){
                        if(v_fileVersions.at(nCounter) != 
			(int)SlnVersions::eight | v_fileVersions.at(nCounter) != 
			(int)SlnVersions::seven)
                            i++;
                    }
                }
            }
        }
        //If there were problems with creating the file, let the user know
        else if(!outputFile.is_open())
        {
            printf("I couldn't open %s for creation!\n", "outputFilePath");
            v_bSucceeded.push_back(false);
            return 0;
        }
        outputFile.close();
        v_bSucceeded.push_back(true);
        v_slnNewVersions.push_back(slnChangeTo);

        nCounter++;
    }
    return;
}

Here a snippet of QueryContextMenu(). With this function, you build up the menu structure with the context menu lable text loaded from the registry.

C++
HRESULT CVSSolutionVersionChangerDll::QueryContextMenu (
    HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
UINT uCmdID = uidFirstCmd;

	SlnVersions slnVer = vc.AnalyzeFileVersion(&m_lsFiles);
	
    // If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
    if ( uFlags & CMF_DEFAULTONLY )
        return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

	HMENU mPopUp = CreatePopupMenu();

	UINT nFlags = MF_STRING | MF_BYPOSITION;
	if(m_lsFiles.size() == 1 &&  slnVer == SlnVersions::seven)
		nFlags = nFlags | MF_GRAYED;

	InsertMenu ( mPopUp,uMenuIndex, nFlags, uCmdID++, cMgr.s2002.c_str() ); 

	uMenuIndex++;

	nFlags = MF_STRING | MF_BYPOSITION;
	if(m_lsFiles.size() == 1 &&  slnVer == SlnVersions::eight)
		nFlags = nFlags | MF_GRAYED;

	InsertMenu ( mPopUp,uMenuIndex, nFlags, uCmdID++, cMgr.s2003.c_str() );

	uMenuIndex++;

	nFlags = MF_STRING | MF_BYPOSITION;
	if(m_lsFiles.size() == 1 &&  slnVer == SlnVersions::nine)
		nFlags = nFlags | MF_GRAYED;

	InsertMenu ( mPopUp,uMenuIndex, nFlags, uCmdID++, cMgr.s2005.c_str() );

	uMenuIndex++;

...		 

Config

On the config dialog, you can set your preferred conversion settings, whether to backup and/or overwrite the original file or you can set the context menu text.

Shot_Config_v1.0.0.2.png

Credits

  • Michael Dunn - The Complete Idiot's Guide to Writing Shell Extensions - Part II

History

  • April 18. 2010 - Version 1.0.0.2
    • New release with support for VS version 2002-2010 and more config options
  • April 03. 2010 - Version 1.0.0.0
    • Initial revision with converter for solution file version 7.00 (7), 8.00 (7.1), 9.00 (8) and 10.00 (9) // FileVersion (IconVersion)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Switzerland Switzerland
programmer and software junkie since 1991 zurich switzerland

Comments and Discussions

 
GeneralMy vote of 5 Pin
mail-2227-Apr-12 1:20
mail-2227-Apr-12 1:20 
GeneralRe: My vote of 5 Pin
kim.david.hauser13-May-13 9:24
kim.david.hauser13-May-13 9:24 
Generalsmall fix Pin
Karpov Andrey25-Dec-10 6:15
Karpov Andrey25-Dec-10 6:15 
GeneralRe: small fix Pin
kim.david.hauser13-May-13 9:26
kim.david.hauser13-May-13 9:26 
GeneralVisual Studio 2003 Build - No Context menu Pin
Stone Free22-Apr-10 0:02
Stone Free22-Apr-10 0:02 
GeneralDLL Built with debug CRT Pin
Stone Free19-Apr-10 23:55
Stone Free19-Apr-10 23:55 
GeneralSuggestion Pin
Adam Maras8-Apr-10 17:23
Adam Maras8-Apr-10 17:23 
GeneralRe: Suggestion Pin
Saurabh.Garg9-Apr-10 16:40
Saurabh.Garg9-Apr-10 16:40 
This is a minor change and you have the source, why not change it yourself?

-Saurabh
NewsRe: Suggestion Pin
kim.david.hauser18-Apr-10 2:16
kim.david.hauser18-Apr-10 2:16 
GeneralWindows 7 x64 Pin
Roberto Guerzoni7-Apr-10 2:36
professionalRoberto Guerzoni7-Apr-10 2:36 
GeneralRe: Windows 7 x64 Pin
kim.david.hauser8-Apr-10 11:51
kim.david.hauser8-Apr-10 11:51 
GeneralRe: Windows 7 x64 Pin
Dave Aronow9-Apr-10 10:56
Dave Aronow9-Apr-10 10:56 
Generalthanks Pin
ryukiy6-Apr-10 14:54
ryukiy6-Apr-10 14:54 
Generalexcellent Pin
Andreone6-Apr-10 9:25
Andreone6-Apr-10 9:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.