1 #region Copyright (c) 2002-2003, James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole, Philip A. Craig
2 /************************************************************************************
4 ' Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
5 ' Copyright 2000-2002 Philip A. Craig
7 ' This software is provided 'as-is', without any express or implied warranty. In no
8 ' event will the authors be held liable for any damages arising from the use of this
11 ' Permission is granted to anyone to use this software for any purpose, including
12 ' commercial applications, and to alter it and redistribute it freely, subject to the
13 ' following restrictions:
15 ' 1. The origin of this software must not be misrepresented; you must not claim that
16 ' you wrote the original software. If you use this software in a product, an
17 ' acknowledgment (see the following) in the product documentation is required.
19 ' Portions Copyright 2002-2003 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov, Charlie Poole
20 ' or Copyright 2000-2002 Philip A. Craig
22 ' 2. Altered source versions must be plainly marked as such, and must not be
23 ' misrepresented as being the original software.
25 ' 3. This notice may not be removed or altered from any source distribution.
27 '***********************************************************************************/
33 using System.Runtime.InteropServices;
35 using System.Collections;
40 /// Static methods for manipulating project paths, including both directories
41 /// and files. Some synonyms for System.Path methods are included as well.
43 public class ProjectPath
45 public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
46 public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
47 public const int MAX_PATH = 256;
49 #region Public methods
51 public static bool IsAssemblyFileType( string path )
53 string extension = Path.GetExtension( path );
54 return extension == ".dll" || extension == ".exe";
59 /// Returns the relative path from a base directory to another
60 /// directory or file.
62 public static string RelativePath( string from, string to )
64 from = Canonicalize( from );
65 to = Canonicalize( to );
67 // Second argument to PathRelativeTo must be absolute
68 if ( !Path.IsPathRooted( to ) )
71 StringBuilder sb = new StringBuilder( MAX_PATH );
73 // Return null if call fails
74 if ( !PathRelativePathTo( sb, from, FILE_ATTRIBUTE_DIRECTORY, to, FILE_ATTRIBUTE_DIRECTORY ) )
77 // Remove initial .\ from path if present
78 if ( sb.Length >=2 && sb[0] == '.' && sb[1] == '\\' )
88 /// Returns the relative path from a base directory to another
89 /// directory or file.
91 public static string RelativePath( string from, string to )
93 char dirSeperator = System.IO.Path.DirectorySeparatorChar;
94 string upDirStr = @"..\";
96 //Start by normalizing paths
97 NormalizePath (ref from);
98 NormalizePath (ref to);
100 if ( !IsPathValid (from) || !IsPathValid (to) )
103 if (!System.IO.Path.IsPathRooted (to))
106 //First check if FullPath begins with the BasePath
107 if ( to.StartsWith (from))
108 return to.Replace (from,".");
110 //Now parse backwards
111 StringBuilder backDirs = new StringBuilder ();
112 string partialPath = from;
113 int index = partialPath.LastIndexOf (dirSeperator);
115 //Strip path step string to last backslash and add another step backwards to our pass replacement
116 partialPath = partialPath.Substring(0,index);
117 backDirs.Append(upDirStr);
119 //check if FullPath begins with the current partialPath
120 if ( to.StartsWith(partialPath) )
121 if ( to == partialPath ) {
122 //Full Directory match and need to replace it all
123 backDirs.Remove (backDirs.Length-1, 1);
124 return backDirs.ToString ();
126 else //We're dealing with a file or a start path
127 return to.Replace (partialPath + dirSeperator, backDirs.ToString ());
129 index = partialPath.LastIndexOf (dirSeperator, partialPath.Length-1);
131 //No common root found, return null.
136 /// Return the canonical form of a path.
137 public static string Canonicalize( string path )
140 StringBuilder sb = new StringBuilder( MAX_PATH );
141 if ( !PathCanonicalize( sb, path ) )
142 throw new ArgumentException( string.Format( "Invalid path passed to PathCanonicalize: {0}", path ) );
144 return sb.ToString();
146 return Path.GetFullPath( path );
151 /// True if the two paths are the same. However, two paths
152 /// to the same file or directory using different network
153 /// shares or drive letters are not treated as equal.
155 public static bool SamePath( string path1, string path2 )
157 return Canonicalize(path1).ToLower() == Canonicalize(path2).ToLower();
161 /// True if the two paths are the same or if the second is
162 /// directly or indirectly under the first. Note that paths
163 /// using different network shares or drive letters are
164 /// considered unrelated, even if they end up referencing
165 /// the same subtrees in the file system.
167 public static bool SamePathOrUnder( string path1, string path2 )
169 path1 = Canonicalize( path1 );
170 path2 = Canonicalize( path2 );
172 int length1 = path1.Length;
173 int length2 = path2.Length;
175 // if path1 is longer, then path2 can't be under it
176 if ( length1 > length2 )
179 // if lengths are the same, check for equality
180 if ( length1 == length2 )
181 return path1.ToLower() == path2.ToLower();
183 // path 2 is longer than path 1: see if initial parts match
184 if ( path1.ToLower() != path2.Substring( 0, length1 ).ToLower() )
187 // must match through or up to a directory separator boundary
188 return path2[length1-1] == Path.DirectorySeparatorChar ||
189 path2[length1] == Path.DirectorySeparatorChar;
195 #region Shlwapi functions used internally
197 [DllImport("shlwapi.dll")]
198 private static extern bool PathRelativePathTo(
199 StringBuilder result,
205 [DllImport("shlwapi.dll")]
206 private static extern bool PathCanonicalize(
207 StringBuilder result,
210 [DllImport("shlwapi.dll")]
211 private static extern int PathCommonPrefix(
214 StringBuilder result );
218 private static bool IsPathValid(string path)
220 return (path!=string.Empty) && (path[0] != System.IO.Path.DirectorySeparatorChar);
223 private static void NormalizePath (ref string path)
225 string dirSeperator = new string (new char [] {System.IO.Path.DirectorySeparatorChar});
227 path = path.ToLower ();
228 if (path.EndsWith (dirSeperator))
229 path = path.Substring (0, path.Length - 1);