65.9K
CodeProject 正在变化。 阅读更多。
Home

Microsoft Visual Studio 解决方案文件版本更改器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (15投票s)

2010年4月6日

CPOL

2分钟阅读

viewsIcon

103119

downloadIcon

4044

Microsoft Visual Studio 解决方案文件版本转换器 - 适用于 Visual Studio 2002、2003、2005、2008 和 2010 版本

引言

该项目是 Windows Explorer Shell 扩展(右键菜单),用于快速更改 Visual Studio 解决方案文件的版本。项目源代码展示了如何创建 Explorer Shell 扩展以及如何在解决方案版本之间进行转换。此 Shell 扩展的基础是 Michael Dunn 的 编写 Shell 扩展的完全傻瓜指南 - 第二部分

Shot_ContextMenu_v1.0.0.2.png

Visual Studio 解决方案文件版本

以下是 Visual Studio 版本的概述,以及文件和产品版本,这可能有点令人困惑,因为涉及了许多不同的版本。

Visual Studio 版本 文件版本 产品版本
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

解决方案文件版本 8.00

直到版本 8.00,您只需要更改 *.sln 文件中第二行的版本号

2003_file.png

解决方案文件版本 9.00

在版本 9.00 及更高版本中,您需要更改第二行和第三行

2005_file.png

Using the Code

一个使用 Visual Studio .NET 2008 编译的 VC++ 项目,但也可以使用 VS2003 编译。它是一个 ATL ComObject,需要使用 regsvr32 注册。代码展示了如何

  • 使用 ATL 创建自注册 COM 对象
  • 转换 Microsoft VS *.sln 文件之间的版本
  • 在 Explorer 上下文菜单中创建带有图标的子菜单

首先,我们分析版本并将原始文件保存到内部结构(字符串向量)

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;
    }

使用以下函数,我们可以将文件转换为所需的任何版本。

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;
}

这里是 QueryContextMenu() 的一个片段。使用此函数,您可以从注册表中加载的上下文菜单标签文本构建菜单结构。

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++;

...		 

配置

在配置对话框中,您可以设置首选转换设置,例如是否备份和/或覆盖原始文件,或者您可以设置上下文菜单文本。

Shot_Config_v1.0.0.2.png

致谢

  • Michael Dunn - 编写 Shell 扩展的完全傻瓜指南 - 第二部分

历史

  • 2010 年 4 月 18 日 - 版本 1.0.0.2
    • 新版本,支持 VS 版本 2002-2010 和更多配置选项
  • 2010 年 4 月 3 日 - 版本 1.0.0.0
    • 初始修订版,包含解决方案文件版本 7.00 (7)、8.00 (7.1)、9.00 (8) 和 10.00 (9) 的转换器 // 文件版本 (图标版本)
© . All rights reserved.