#region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig /************************************************************************************ ' ' Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole ' Copyright 2000-2002 Philip A. Craig ' ' This software is provided 'as-is', without any express or implied warranty. In no ' event will the authors be held liable for any damages arising from the use of this ' software. ' ' Permission is granted to anyone to use this software for any purpose, including ' commercial applications, and to alter it and redistribute it freely, subject to the ' following restrictions: ' ' 1. The origin of this software must not be misrepresented; you must not claim that ' you wrote the original software. If you use this software in a product, an ' acknowledgment (see the following) in the product documentation is required. ' ' Portions Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole ' or Copyright 2000-2002 Philip A. Craig ' ' 2. Altered source versions must be plainly marked as such, and must not be ' misrepresented as being the original software. ' ' 3. This notice may not be removed or altered from any source distribution. ' '***********************************************************************************/ #endregion using System; using System.IO; using System.Xml; namespace NUnit.Util { /// /// This class allows loading information about /// configurations and assemblies in a Visual /// Studio project file and inspecting them. /// Only the most common project types are /// supported and an exception is thrown if /// an attempt is made to load an invalid /// file or one of an unknown type. /// public class VSProject { #region Static and Instance Variables /// /// VS Project extentions /// private static readonly string[] validExtensions = { ".csproj", ".vbproj", ".vjsproj", ".vcproj" }; /// /// VS Solution extension /// private static readonly string solutionExtension = ".sln"; /// /// Path to the file storing this project /// private string projectPath; /// /// Collection of configs for the project /// private VSProjectConfigCollection configs; #endregion #region Constructor public VSProject( string projectPath ) { this.projectPath = Path.GetFullPath( projectPath ); configs = new VSProjectConfigCollection(); Load(); } #endregion #region Properties /// /// The name of the project. /// public string Name { get { return Path.GetFileNameWithoutExtension( projectPath ); } } /// /// The path to the project /// public string ProjectPath { get { return projectPath; } } /// /// Our collection of configurations /// public VSProjectConfigCollection Configs { get { return configs; } } #endregion #region Static Methods public static bool IsProjectFile( string path ) { string extension = Path.GetExtension( path ); foreach( string validExtension in validExtensions ) if ( extension == validExtension ) return true; return false; } public static bool IsSolutionFile( string path ) { return Path.GetExtension( path ) == solutionExtension; } #endregion #region Instance Methods public void Load() { if ( !IsProjectFile( projectPath ) ) ThrowInvalidFileType( projectPath ); string projectDirectory = Path.GetFullPath( Path.GetDirectoryName( projectPath ) ); try { XmlDocument doc = new XmlDocument(); doc.Load( projectPath ); string extension = Path.GetExtension( projectPath ); string assemblyName; switch ( extension ) { case ".vcproj": foreach ( XmlNode configNode in doc.SelectNodes( "/VisualStudioProject/Configurations/Configuration" ) ) { string name = configNode.Attributes["Name"].Value; string outputPath = configNode.Attributes["OutputDirectory"].Value; string outputDirectory = Path.Combine( projectDirectory, outputPath ); XmlNode toolNode = configNode.SelectSingleNode( "Tool[@Name='VCLinkerTool']" ); assemblyName = Path.GetFileName( toolNode.Attributes["OutputFile"].Value ); string assemblyPath = Path.Combine( outputDirectory, assemblyName ); VSProjectConfig config = new VSProjectConfig ( name ); config.Assemblies.Add( assemblyPath ); this.configs.Add( config ); } break; case ".csproj": case ".vbproj": case ".vjsproj": XmlNode settingsNode = doc.SelectSingleNode( "/VisualStudioProject/*/Build/Settings" ); assemblyName = settingsNode.Attributes["AssemblyName"].Value; string outputType = settingsNode.Attributes["OutputType"].Value; if ( outputType == "Exe" || outputType == "WinExe" ) assemblyName = assemblyName + ".exe"; else assemblyName = assemblyName + ".dll"; XmlNodeList nodes = settingsNode.SelectNodes("Config"); if ( nodes != null ) foreach ( XmlNode configNode in nodes ) { string name = configNode.Attributes["Name"].Value; string outputPath = configNode.Attributes["OutputPath"].Value; string outputDirectory = Path.Combine( projectDirectory, outputPath ); string assemblyPath = Path.Combine( outputDirectory, assemblyName ); VSProjectConfig config = new VSProjectConfig ( name ); config.Assemblies.Add( assemblyPath ); configs.Add( config ); } break; default: break; } } catch( FileNotFoundException ) { throw; } catch( Exception e ) { ThrowInvalidFormat( projectPath, e ); } } private void ThrowInvalidFileType( string projectPath ) { throw new ArgumentException( string.Format( "Invalid project file type: {0}", Path.GetFileName( projectPath ) ) ); } private void ThrowInvalidFormat( string projectPath, Exception e ) { throw new ArgumentException( string.Format( "Invalid project file format: {0}", Path.GetFileName( projectPath ) ), e ); } #endregion } }