Click here to Skip to main content
Click here to Skip to main content

Microsoft Visual Studio Solution File Version Changer

, 18 Apr 2010
Rate this:
Please Sign up or sign in to vote.
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 Version File Version Product Version
Microsoft Visual Studio .NET (2002) 7.00 7
Visual Studio 2003 8.00 7.1
Visual Studio 2005 9.00 8
Visual Studio 2008 10.00 9
Visual Studio 2010 11.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):

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.

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.

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)

Share

About the Author

kim.david.hauser
Software Developer (Senior)
Switzerland Switzerland
programmer and software junkie since 1991 zurich switzerland
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermail-2227-Apr-12 1:20 
GeneralRe: My vote of 5 Pinmemberkim.david.hauser13-May-13 9:24 
Generalsmall fix PinmemberKarpov Andrey25-Dec-10 6:15 
GeneralRe: small fix Pinmemberkim.david.hauser13-May-13 9:26 
GeneralVisual Studio 2003 Build - No Context menu PinmemberStone Free22-Apr-10 0:02 
GeneralDLL Built with debug CRT PinmemberStone Free19-Apr-10 23:55 
GeneralSuggestion PinmemberAdam Maras8-Apr-10 17:23 
GeneralRe: Suggestion PinmemberSaurabh.Garg9-Apr-10 16:40 
NewsRe: Suggestion Pinmemberkim.david.hauser18-Apr-10 2:16 
GeneralWindows 7 x64 PinmemberRoberto Guerzoni7-Apr-10 2:36 
GeneralRe: Windows 7 x64 Pinmemberkim.david.hauser8-Apr-10 11:51 
GeneralRe: Windows 7 x64 PinmemberDave Aronow9-Apr-10 10:56 
Generalthanks Pinmemberryukiy6-Apr-10 14:54 
Generalexcellent PinmemberAndreone6-Apr-10 9:25 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 18 Apr 2010
Article Copyright 2010 by kim.david.hauser
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid