home *** CD-ROM | disk | FTP | other *** search
- # -*- tcl -*-
- # Uninstallation script for ActiveTcl
- # ----------------------------------------------
- #
- # Copyright 2001, ActiveState Corp.
- # All Rights Reserved.
-
- #
- # This should be run using the ActiveTcl wish version that we will be
- # uninstalling
- #
-
- # This can be used with 8.3.3.3+
-
- package require ActiveTcl 8.3.3.3
- package require Tk
- package require BWidget
-
- option add *Button.highlightthickness 1
- option add *Scrollbar.highlightthickness 1
- option add *Text.highlightthickness 1
- option add *Label.highlightthickness 0
- option add *Label.borderWidth 0
-
- set ::WELCOME "Uninstaller for ActiveTcl $::activestate::config(release).
-
- Select 'Next' to begin uninstalling.
- "
-
- # ----------------------------------------------
-
- proc main {} {
- wm protocol . WM_DELETE_WINDOW exit
- wm title . "ActiveTcl $::activestate::config(release) Uninstaller"
-
- # Read the logo and create an image from it.
-
- set logo [image create photo -file \
- [file join $::tk_library images ActiveTclSplash.gif]]
-
- set left [frame .left]
- set ::BASE [PagesManager .right]
- set sep [frame .sep -height 2 -bd 2 -relief sunken]
- set ::BTNS [frame .btns]
-
- label $left.logo -image $logo
- pack $left.logo -expand 1 -fill both
-
- grid $left $::BASE -sticky news
- grid $sep -columnspan 2 -sticky ew
- grid $::BTNS -columnspan 2 -sticky ew
- grid columnconfig $::BTNS 0 -weight 1
- grid columnconfig . 1 -weight 1
- grid rowconfigure . 0 -weight 1
-
- set ::CANCEL [button $::BTNS.cncl -text "Cancel" -command { cancel }]
- set ::NEXT [button $::BTNS.next -text "Next >" -command {set ::WAIT 1}]
-
- grid $::NEXT $::CANCEL -sticky e -padx 4 -pady 8
-
- # Note: The procedures open and manipulate the user interface.
- # They use [vwait] to enter the eventloop where needed so that
- # sequencing control is not taken from [main].
-
- uninstall $::BASE
-
- exit 0
- }
-
- # ----------------------------------------------
-
- proc uninstall {pages} {
- set pname uninstall
- set page [$pages getframe $pname]
- set firsttime 0
- if {![winfo exists $page]} {
- set firsttime 1
- set page [$pages add $pname]
- grid [ScrolledWindow $page.s -auto both] -sticky news -padx 4 -pady 4
- set tw [text $page.s.t -width 20 -height 8]
- $page.s setwidget $tw
-
- grid columnconfigure $page 0 -weight 1
- grid rowconfigure $page 0 -weight 1
-
- $tw insert 1.0 $::WELCOME
- $tw configure -state disabled
- $tw tag configure error -background #CC4444
-
- # Accept focus even when disabled
- bind $tw <1> { focus %W }
- bind $tw <Key-Return> { next }
- }
- $pages raise $pname
- set ::LOGWIN $page.s.t
-
- set res [wait_next]
- if {$res < 0} { return $res }
-
- # At this point, there is only cancel
- $::NEXT configure -state disabled
-
- # Uninstall stuff
- do_uninstall_modules
-
- # This only allows exit
- if {[string equal "windows" $::tcl_platform(platform)]} {
- wait_next 0 "Finish"
- } else {
- wait_next 0 "Exit"
- }
- }
-
- # ----------------------------------------------
- # WAIT ROUTINES
- # ----------------------------------------------
-
- proc next {} { $::NEXT invoke }
- proc cancel {} { exit 0 }
-
- proc wait_next {{next 1} {cancel "Cancel"}} {
- if {$next} { grid $::NEXT } else { grid remove $::NEXT }
- $::NEXT configure -state normal -command [list set ::WAIT $next]
- $::CANCEL configure -text $cancel -state normal -command cancel
-
- vwait ::WAIT
- return $::WAIT
- }
-
- # ----------------------------------------------
- # LOGGING ROUTINE
- # ----------------------------------------------
-
- proc log {msg {type ok}} {
- if {[string length $msg]} {
- $::LOGWIN configure -state normal
- $::LOGWIN insert end "$msg\n" $type
- $::LOGWIN see end
- $::LOGWIN configure -state disabled
- update
- }
- }
-
- proc do_uninstall_modules {} {
- log "\nUninstalling ActiveTcl $::activestate::config(release) ..."
- log "Reading in INSTALL.LOG ..."
-
- set data ""
- set ver $::activestate::config(release)
- set isCurrentVersion 0
- if {[string equal "windows" $::tcl_platform(platform)]} {
- package require registry
- package require dde
- set key {HKEY_LOCAL_MACHINE\SOFTWARE\ActiveState\ActiveTcl}
- if {[catch {registry get "$key\\$ver" ""} verdir]} {
- log "Inconsistent uninstall state.\nABORTING UNINSTALL."
- }
- if {[catch {
- set fh [open $verdir/INSTALL.LOG]
- set data [read $fh]
- close $fh
- } err]} {
- log "ERROR: $err" error
- }
- if {![catch {registry get $key "CurrentVersion"} curver] \
- && [string equal $curver $ver]} {
- set isCurrentVersion 1
- } else {
- # Only when we are the current version do we want
- # to delete all the added keys
- log "Deleting registry key $key\\$ver"
- if {[catch {
- registry delete "$key\\$ver"
- } err]} {
- log "ERROR: $err" error
- }
- }
- log "Deleting registry key HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ActiveTcl $ver"
- if {[catch {
- registry delete "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ActiveTcl $ver"
- } err]} {
- log "ERROR: $err" error
- }
- if {[string equal "Windows NT" $::tcl_platform(os)]} {
- set regPath {HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment}
- set bindir $verdir\\bin
- log "Removing \"$bindir\" from your executable path ..."
- if {[catch {
- set curPath [registry get $regPath Path]
- registry set $regPath Path [string map -nocase \
- [list "$bindir;" {}] $curPath] expand_sz
- } err]} { log "ERROR: $err" error }
- }
- # We don't remove the .tcl in PATHEXT
- } else {
- if {[catch {
- set fh [open [file dirname [file dirname \
- [info nameofexec]]]/INSTALL.LOG]
- set data [read $fh]
- close $fh
- } err]} {
- log "ERROR: $err" error
- }
- }
-
- set dirs ""
- set files ""
- foreach line [split $data \n] {
- if {$line == "" || [string match "#*" $line]} { continue }
- switch -exact [lindex $line 0] {
- MKDIR {
- set dir [lindex $line 1]
- if {[file isdirectory $dir]} { lappend dirs $dir }
- }
- FILECOPY {
- set file [lindex $line 1]
- if {[file exists $file]} { lappend files $file }
- }
- REGKEY {
- foreach {cmd skey value data} $line { break }
- if {$isCurrentVersion} {
- log "Deleting registry key $skey $value"
- # We don't worry about errors here - we only
- # care the the reg key is gone.
- catch {registry delete $skey $value}
- }
- }
- PROGGROUP {
- set group [lindex $line 1]
- log "Deleting Program Group $group"
- if {[catch {
- dde execute progman progman "\[DeleteGroup($group)\]"
- } err]} {
- log "dde returned: $err"
- }
- }
- default {
- log "Unknown LOG instruction \"$line\""
- }
- }
- }
- if {[string equal "windows" $::tcl_platform(platform)] && \
- ([llength $files] || [llength $dirs])} {
- if {[info exists ::env(TEMP)]} {
- set uninst [file join $::env(TEMP) at-unins.bat]
- } elseif {[info exists ::env(TMP)]} {
- set uninst [file join $::env(TMP) at-unins.bat]
- } else {
- set uninst "C:/at-unins.bat"
- }
- if {[catch {open $uninst w} fid]} {
- log "ERROR: Unable to create bat file to remove files" error
- } else {
- # A little hacky, but on Windows, since we can't delete
- # Ourselves, we wait on the "Finish" to launch a batch file
- # which does the file and directory removal
- rename exit real_exit
- set cmd [concat [auto_execok start] " \"$uninst\""]
- proc exit args "exec $cmd & ; uplevel 1 real_exit \$args"
- puts $fid "@ECHO OFF"
- puts $fid "REM This script removes the installation files"
- puts $fid "REM for ActiveTcl $ver. It can be deleted after run.\n"
- puts $fid "REM Make sure we are not in the install directory."
- puts $fid "CD C:\\"
- if {[string equal "Windows NT" $::tcl_platform(os)]} {
- # NT/2K batch scripting is a bit more enhanced
- # All the extras aren't really necessary, but my purist
- # scripting heart likes this better.
- puts $fid "ECHO Press Return to remove all files installed\
- with ActiveTcl $ver ..."
- puts $fid "PAUSE > NUL"
-
- # Files removed in a for loop
- puts $fid "FOR %%Z IN ("
- foreach file [lsort -unique -decreasing $files] {
- set file [file nativename \
- [file attributes $file -shortname]]
- puts $fid " $file"
- }
- puts $fid ") DO ("
- puts $fid " IF EXIST %%Z ("
- puts $fid " ECHO Removing file \"%%Z\""
- puts $fid " DEL /F \"%%Z\""
- puts $fid " )"
- puts $fid ")"
-
- # Dirs removed in a for loop
- puts $fid "REM Check to see that the directory is empty first"
- puts $fid "FOR %%Z IN ("
- # The lsort -decr sorts them in depth-first order
- foreach dir [lsort -unique -decreasing $dirs] {
- set dir [file nativename [file attributes $dir -shortname]]
- puts $fid " $dir"
- }
- puts $fid ") DO ("
- puts $fid " IF EXIST %%Z\\nul ("
- puts $fid " DIR %%Z | FIND \" 0 bytes\" > NUL"
- puts $fid " IF NOT ERRORLEVEL==1 ("
- puts $fid " ECHO Removing directory \"%%Z\""
- puts $fid " RMDIR %%Z"
- puts $fid " )"
- puts $fid " )"
- puts $fid ")"
-
- # All done now
- puts $fid "ECHO Done. Press Return to exit ..."
- puts $fid "PAUSE > NUL"
- } else {
- # Due to bug 232731, we can only delay on Win9*, not PAUSE
- puts $fid "ECHO Removing all files installed\
- with ActiveTcl $ver ..."
- puts $fid "TYPE NUL | CHOICE.COM /N /CY /TY,3 >NUL"
-
- # This is more brute force, but Win9* batch scripting stinks.
- foreach file [lsort -unique -decreasing $files] {
- set file [file nativename \
- [file attributes $file -shortname]]
- puts $fid "ECHO Removing \"$file\""
- puts $fid "IF EXIST $file DEL $file"
- }
-
- # The lsort -decr sorts them in depth-first order
- foreach dir [lsort -unique -decreasing $dirs] {
- set dir [file nativename [file attributes $dir -shortname]]
- puts $fid "ECHO Removing \"$dir\""
- puts $fid "IF EXIST $dir\\nul\
- DIR $dir | FIND \" 0 bytes\" > NUL"
- puts $fid "IF NOT ERRORLEVEL==1 RMDIR $dir"
- }
-
- # All done now
- puts $fid "ECHO Done. Exiting ..."
- puts $fid "TYPE NUL | CHOICE.COM /N /CY /TY,2 >NUL"
- }
-
- puts $fid "EXIT"
- close $fid
- }
-
- log ""
- log "All other Tcl/Tk applications must be closed before finishing ..."
- log "Press Finish to uninstall associated files ..."
- } else {
- foreach file $files {
- log "Removing file $file"
- if {[catch {file delete -force $file} err]} {
- log "ERROR: $err" error
- }
- }
-
- # The lsort -decr sorts them in depth-first order
- foreach dir [lsort -unique -decreasing $dirs] {
- if {[llength [glob -nocomplain $dir/*]] == 0} {
- log "Removing empty directory $dir"
- if {[catch {file delete -force $dir} err]} {
- log "ERROR: $err" error
- }
- } else {
- log "Leaving non-empty directory $dir"
- }
- }
-
- log "Done ..."
- }
-
- return
- }
-
- # ----------------------------------------------
- # ----------------------------------------------
-
- set ::SCRIPT_DIR [file dirname [info script]]
- set here [pwd] ; cd $::SCRIPT_DIR ; set ::SCRIPT_DIR [pwd] ; cd $here
-
- if {[catch {
- main
- } err]} {
- catch {bgerror $err}
- }
- exit
-