Version 1 of Visual Studio 2003 .sln file parser

Updated 2004-02-02 17:47:44

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

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