Version 3 of Visual Studio 2003 .sln file parser

Updated 2004-02-02 17:50:54

I needed to find the web projects in a specific Visual Studio 2003 solution (.sln) file. Here's how I did it...

 ### Script to clear Visual Studio's web cache for projects in a given solution file.

 variable VS2K3VersionString "Microsoft Visual Studio Solution File, Format Version 8.00"

 # We need the uri package to parse the project URLs
 package require uri

 proc find_projects {sln_body} {
         # Returns a list containing the projects in the solution.  Each list item is itself a list: 
         # element 0 is the project name, element 1 is the location for the project
         variable VS2K3VersionString  
         set projects_out [list]

         if {[string first $VS2K3VersionString $sln_body] != 0} {
                 error "This doesn't appear to be a VS2003 solution file.  I don't know what to do with it."
         }
         set sln_body [string range $sln_body [string length $VS2K3VersionString] end]

         # An arbitrary unicode character used to mark the end of projects so we can split the projects
         set arbitrary_unicode_char \u9999

         set sln_body [string map [list {EndProjectSection} {EndProjectSection} {EndProject} "EndProject${arbitrary_unicode_char}"] $sln_body]

         # Split the sln_body into projects and drop all the non-project stuff at the end of the .sln
         # This assumes that projects are always at the beginning of the .sln file.
         # We also assume that there is non-project stuff in the .sln following the projects - 
         # lrange trims off everything after the last project
         set projects [lrange [split $sln_body $arbitrary_unicode_char] 0 end-1]

         foreach p $projects {
                 set p [string trim $p]
                 set temp [string range $p [expr {[string first "=" $p]+1}] end]
                 foreach {name location} [split $temp ","] {break}

                 set name [string trim [string map [list {"} {}] $name]]
                 set location [string trim [string map [list {"} {}] $location]]

                 lappend projects_out [list $name $location]
         }

         return $projects_out
 }

 proc find_web_projects {sln_body} {
 # Returns just the web projects in a solution
         set projects_out [list]
         set plist [find_projects $sln_body]

         foreach project $plist {
                 foreach {name location} $project {break}

                 if {[string match "http://*" $location]} {
                         lappend projects_out $project
                 }
         }

         return $projects_out

 }

 proc clear_web_cache {sln_body cache_dir} {
         foreach project [find_web_projects $sln_body] {
                 foreach {name url} $project {break}

                 array set url_arr [uri::split $url]

                 if {[string equal "localhost" $url_arr(host)]} {
                         set url_arr(host) [info hostname]
                 }
                 set url_arr(host) [string toupper $url_arr(host)]

                 set path_to_delete [file join $cache_dir $url_arr(host) [file dirname $url_arr(path)]]

                 if {[file exists $path_to_delete] && [file isdirectory $path_to_delete]} {
                         file delete -force $path_to_delete
                         puts "Deleted cache directory $path_to_delete"
                 }
         }
 }

 # Usage sample: 
 clear_web_cache SomeSolution.sln [file join $env(USERPROFILE) VSWebCache]

-- Joseph Anderson