噬神者2存档继承:Visual Studio各种版本之间的转换工具

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 16:02:06
    • 装扮主页
    • 修改资料
    • 情侣空间
    • 全部好友
    • 寻找好友
    • 通讯录
    • 邀请朋友
    • 帐户设置
    • VIP中心
    • 充值中心
    退出


    在Codeproject看见这个Visual Studio版本转换的工具,觉得很不错,分享一下给大家,希望对你有所帮助。作者是:CodeBureau - Matt Simner,原地址是:SolutionConverter 。


    Introduction

     

    SolutionConverter will convert a complete Visual Studio solution from one version to another; it allows you to convert your solutions to both older and newer versions. Currently, Visual Studio 2005, 2008, and 2010 are supported, including Visual C# Express and Visual Basic Express editions. Visual C++ project conversion is not yet supported.

     

     

     

    Background

     

    I recently upgraded to Visual Studio 2010 at home and encountered the dreaded problem of opening my solutions in older Visual Studio versions. I attend H.I.T. where they have yet to install the new version, so I simply can't open my work on the institute's computers. After doing some research, I found this very nice article, but unfortunately, the application didn't support Visual Studio 2010 solutions when I started working on this project. Another thing I noticed that was missing was that it only changed the solution file and did not touch the project files, which also have to be edited for a smooth conversion.

     

    So I decided to write my own tool with a view into the future, with simpler code which should allow easier extension in the future.

     

    Looking through Google some more, this page popped up, explaining what exactly needed to be changed in the solution and project files to make the conversion work without any issues. I recommend going over it before continuing with the article to easily understand why the code is written the way it is.

     

    Using the Code

     

    This code will demonstrate the following:

     

    Loading and analyzing a solution file. Detecting the version of Visual Studio it was intended for, and extracting the list of projects the solution contains.

    Loading and analyzing the project files.

    Converting the Solution file into the target version.

    Working with the XML file, and converting the project files into the target version.

    Loading the solution file and determining the solution version:

     Collapse

    /// Retrieves the solution version from the file.

    protected VisualStudioVersion GetSolutionVersion()

    {

        VisualStudioVersion solVer = VisualStudioVersion.Unknown;

        TextReader reader = new StreamReader(this.solutionPath);

        string sln = reader.ReadToEnd();

        reader.Close();

     

        // Here we loop through the possible Visual Studio versions. 

        // Trying to determine the version of our solution.

        foreach (VisualStudioVersion version in Enum.GetValues(

                 typeof(VisualStudioVersion)))

        {

            if (sln.Contains(version.GetStringValue()))

            {

                solVer = version;

            }

        }

     

        return solVer;

    }

    VisualStudioVersion is an enum which represents the possible Visual Studio versions. The enum values use a custom attribute called StringValueAttribute, which allows an enum value to have a sort of 'ToString' method, GetStringValue(). GetStringValue() is a generic extension method which extracts the string value from the first StringValueAttribute occurrence on the specific enum value. To make it clearer, here is the enum definition:

     

     Collapse

    /// Lists all possible solution versions.

    public enum VisualStudioVersion

    {

        /// Unknown Visual Studio version.

        [StringValue("Unknown")]

        Unknown,        

        /// Visual Studio 2002.

        [StringValue("Format Version 7.00")]

        VisualStudio2002 = 2002,

        /// Visual Studio 2003.

        [StringValue("Format Version 8.00")]

        VisualStudio2003 = 2003,

        /// Visual Studio 2005.

        [StringValue("Format Version 9.00")]

        VisualStudio2005 = 2005,

        /// Visual Studio 2008.

        [StringValue("Format Version 10.00")]

        VisualStudio2008 = 2008,

        /// Visual Studio 2010.

        [StringValue("Format Version 11.00")]

        VisualStudio2010 = 2010,

    }

    As you can see, the string values simply represent the values that will appear in the solution file. By simply checking which of these strings the solution file contains, we can determine the Visual Studio version.

     

    In a similar fashion, we can determine the specific IDE the solution was created in, such as Visual Studio or some of the Express editions.

     

     Collapse

    /// Gets the IDE version.

    protected IdeVersion GetIdeVersion()

    {

        IdeVersion ideVer = IdeVersion.Default;

        TextReader reader = new StreamReader(this.solutionPath);

        string sln = reader.ReadToEnd();

        reader.Close();

     

        // Here we loop through the possible Visual Studio versions. 

        // Trying to determine the IDE version.

        foreach (IdeVersion version in Enum.GetValues(typeof(IdeVersion)))

        {

            if (sln.Contains(version.GetStringValue()))

            {

                ideVer = version;

            }

        }

     

        return ideVer;

    }

     

    /// Lists all possible IDE versions.

    public enum IdeVersion

    {

        /// Using the default version or Unknown.

        [StringValue(null)]

        Default,

        /// The full Visual Studio version.

        [StringValue("Visual Studio")]

        VisualStudio,

        /// C# Express Edition.

        [StringValue("Visual C# Express")]

        CSExpress,

        /// Visual Basic Express Edition.

        [StringValue("Visual Basic Express")]

        VBExpress

    }

    Now that we know what the environment in which the solution was created in, we can continue and convert the solution into the target version in which the solution was created in.

     

     Collapse

    public ConversionResult ConvertTo(VisualStudioVersion solutionVersion, IdeVersion ideVersion)

    {

        ...

     

        bool success = true;

        StreamReader reader = new StreamReader(this.solutionPath);

        FileStream stream = null;

        TextWriter writer = null;

        string sln = reader.ReadToEnd();

        reader.Close();

     

        // Replace the solution version.

        sln = sln.Replace(this.VisualStudioVersion.GetStringValue(), 

                          solutionVersion.GetStringValue());

     

        // If possible, also update the IDE version as well.

        if (ideVersion != IdeVersion.Default && this.IdeVersion != IdeVersion.Default)

        {

            string oldVersion, newVersion;

            oldVersion = this.IdeVersion.GetStringValue() + " " + 

                            ((int)this.VisualStudioVersion).ToString();

            newVersion = ideVersion.GetStringValue() + " " + 

                       ((int)solutionVersion).ToString();

            sln = sln.Replace(oldVersion, newVersion);

        }

     

        // Now write the file back to the hard drive.

        try

        {

            stream = File.OpenWrite(this.solutionPath);

            writer = new StreamWriter(stream, Encoding.UTF8);

            writer.Write(sln);

        }

        catch (Exception)

        {

            success = false;

        }

        finally

        {

            this.IsReady = false;

            if (stream != null)

            {

                writer.Close();

            }

        }

     

        ...

    }

    It is that simple, in C#, to convert the solution from one version to another. Now, we also need to convert the projects. We use a Regex expression and a LINQ query to retrieve the path and filename of every project in the solution:

     

     Collapse

    private void ConvertProjects(VisualStudioVersion solutionVersion)

    {

        using (StreamReader reader = File.OpenText(this.solutionPath))

        {

            List projectStrings = new List();

            IConverter projectConverter;

            string projectName, path;

            int index;

     

            // A bit messy, but gets the job done.

            // Retrieve the actual path of the solution.

            path = this.solutionPath.Remove(this.solutionPath.IndexOf(

                      Path.GetFileName(this.solutionPath)), 

                      Path.GetFileName(this.solutionPath).Length);

            this.projectConversionResults.Clear();

     

            // Selects all the strings that contain the "Project("{xxxxxxxx

            //    -xxxx-xxxx-xxxx-xxxxxxxxxxxx}") = "Name", "Name\Name.xxproj","

            // signature.

            projectStrings.AddRange(

               from Match match in this.projectPathRegex.Matches(reader.ReadToEnd())

               where match.Success

               select match.Value);

     

            // Here we attempt to convert all the projects

            // and save the conversion results.

            foreach (string projectString in projectStrings)

            {

                // Cut string down to only contain the solution relative path.

                projectName = projectString.TrimEnd(new char[] { ' ', ',', '\"' });

                index = projectName.LastIndexOf('\"') + 1;

                projectName = path + projectName.Substring

                (index, projectName.Length - index);

                projectConverter = null;

     

                // Make sure we don't crash the program

                // by trying to convert a Visual C++ project

                if (!Path.GetExtension(projectName).Contains("vc"))

                {

                    projectConverter = new ProjectConverter(projectName);

                }

                else

                {

                    // Reserved for a Visual C++ Project converter here.

                }

     

                if (projectConverter != null)

                {

                    this.projectConversionResults.Add(

                             projectConverter.ConvertTo(solutionVersion));

                }

            }

        }

    }

    The code above creates a ProjectConverter object for each of the solution's projects, invokes the Convert method, and adds the conversion result to the ConversionResults collection.

     

    Now we need to identify the project version we are working on. Since the solution file is a formatted text file, all we have to do is read it, replace the relevant values, and save it. Things change when working on project files. Project files in Visual Studio are XML files that contain all the relevant information and settings for the project. These files also rely on the XML namespace 'http://schemas.microsoft.com/developer/msbuild/2003'. There are four elements and attributes that we are going to need access to (as per this):

     

    ToolsVersion attribute

    ProductVersion element

    TargetFrameworkVersion element

    Project attribute of the Import element

    Reading the information from the file and into the XElement and XAttribute objects:

     

     Collapse

    public bool Reload()

    {

        try

        {

            this.project = XDocument.Load(this.projectPath);

        }

        catch (Exception)

        {

            this.project = null;

        }

     

        bool ret = false;

        this.vsVersion = VisualStudioVersion.Unknown;

        this.IsReady = false;

        if (this.project != null)

        {

            this.toolsVersion = this.project.Root.Attribute(XName.Get("ToolsVersion"));

            this.productVersion = this.project.Root.Element(XName.Get("PropertyGroup", 

                                  this.namespaceName)).Element(XName.Get(

                                  "ProductVersion", this.namespaceName));

            this.targetFrameworkVersion = this.project.Root.Element

                    (XName.Get("PropertyGroup", 

                                         this.namespaceName)).Element(XName.Get(

                                         "TargetFrameworkVersion", this.namespaceName));

            this.importProject = this.project.Root.Element(XName.Get("Import", 

                                 this.namespaceName)).Attribute(XName.Get("Project"));

            this.Name = Path.GetFileNameWithoutExtension(this.projectPath);

     

            this.vsVersion = this.GetVsVersion();

            this.IsReady = true;

            ret = true;

        }

     

        return ret;

    }

    Here is the code that we can use to determine which Visual Studio version this project belongs to:

     

     Collapse

    /// Gets the Visual Studio version of the current project.

    private VisualStudioVersion GetVsVersion()

    {

        VisualStudioVersion vsVer = VisualStudioVersion.Unknown;

     

        double product;

        if (Double.TryParse(this.productVersion.Value, out product))

        {

            if (product == 7)

            {

                vsVer = VisualStudioVersion.VisualStudio2002;

            }

            else if (product == 7.1)

            {

                vsVer = VisualStudioVersion.VisualStudio2003;

            }

            else if (product == 8)

            {

                vsVer = VisualStudioVersion.VisualStudio2005;

            }

            else if (product == 9)

            {

                vsVer = VisualStudioVersion.VisualStudio2008;

            }

            else if (product == 10)

            {

                vsVer = VisualStudioVersion.VisualStudio2010;

            }

        }

     

        return vsVer;

    }

    And here is the code used to convert the projects. What we do is remove or add the relevant attributes or elements to the XML file, saving it afterwards. Since we are working directly with an XML object, we will receive a valid XML file after this procedure, ready to be used in a different Visual Studio version.

     

     Collapse

    public ConversionResult ConvertTo(VisualStudioVersion vsVersion)

    {

        ...

     

        // Calling the relevant method for editing

        // the attributes and elements of the XML.

        switch (vsVersion)

        {

            case VisualStudioVersion.VisualStudio2002:

                this.ConvertToVs2002(vsVersion);

                break;

            case VisualStudioVersion.VisualStudio2003:

                this.ConvertToVs2003(vsVersion);

                break;

            case VisualStudioVersion.VisualStudio2005:

                this.ConvertToVs2005(vsVersion);

                break;

            case VisualStudioVersion.VisualStudio2008:

                this.ConvertToVs2008(vsVersion);

                break;

            case VisualStudioVersion.VisualStudio2010:

                this.ConvertToVs2010(vsVersion);

                break;

        }

     

        // Saving the Project XML file.

        FileStream fileStream = null;

        XmlTextWriter writer = null;

        ret.ConverterReference = this;

        try

        {

            fileStream = new FileStream(this.projectPath, FileMode.Create);

            writer = new XmlTextWriter(fileStream, Encoding.UTF8);

            writer.Formatting = Formatting.Indented;

            this.project.WriteTo(writer);

            ret.ConversionStatus = ConversionStatus.Succeeded;

        }

        catch (Exception)

        {

            ret.ConversionStatus = ConversionStatus.Failed;

        }

        finally

        {

            this.IsReady = false;

            if (writer != null)

            {

                writer.Close();

            }

        }

     

        return ret;

    }

     

    /// Converts to VS2008 version.

    private void ConvertToVs2008(VisualStudioVersion vsVersion)

    {

        if (this.toolsVersion != null)

        {

            double tools;

            if (Double.TryParse(this.toolsVersion.Value, out tools) && tools != 3.5)

            {

                this.toolsVersion.Value = "3.5";

            }

        }

        else

        {

            this.project.Root.Add(new XAttribute(XName.Get("ToolsVersion"), "3.5"));

        }

     

        if (this.productVersion != null)

        {

            this.productVersion.Value = "9.0.21022";

        }

     

        if (this.targetFrameworkVersion != null)

        {

            double framework;

            if (Double.TryParse(

                this.targetFrameworkVersion.Value.Substring(1, 

                       this.targetFrameworkVersion.Value.Length - 2),

                       out framework) && framework > 3.5)

            {

                this.targetFrameworkVersion.Value = "v3.5";

            }

        }

        else

        {

            XElement newToolsVersion = new XElement(XName.Get("TargetFrameworkVersion", 

                                           this.namespaceName), "v2.0");

            this.project.Root.Element(XName.Get("PropertyGroup", 

                                      this.namespaceName)).Add(newToolsVersion);

        }

     

        if (this.importProject != null && 

                 !this.importProject.Value.Contains("$(MSBuildToolsPath)"))

        {

            this.importProject.Value = 

              this.importProject.Value.Replace("$(MSBuildBinPath)", "$(MSBuildToolsPath)");

        }

    }

    References and Inspirations

     

    Microsoft Visual Studio Solution File Version Changer

    Visual Studio Version Interoperability

    How to use solutions and projects between Visual Studio 2005 and 2008

    History

     

    6 May, 2010 - Version 1.0.3779.3862 - Initial release.

    9 May, 2010 - Updated source code (included DLL).

    27 May, 2010 - Updated article text.

    License

     

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

     

    About the Author

     

    Arthur Liberman

     

     

    Member A 2nd year student majoring in Computer Science at Holon Institute of Technology.

    Occupation: Software Developer

    Location: Israel