Arjen Markus (4 november 2003) I have put this little script on the Wiki, because questions as to how to deal with "installations" came up on the starkit mailing list.
The idea is simple:
- Put the directory structure of your application (consisting of whatever files) in a subdirectory "myapp" of a separate but ordinary starkit/starpack
- Use this little script as the code to be run
- Create a starpack out of the whole directory
So here is an example:
./install.vfs/
main.tcl
lib/
app-install/
install.tcl
pkgIndex.tcl <--- All standard starkit stuff!
myapp/ <--- Copy of the directory to hold all
bin/ files in the application
exe1
exe2
lib/
config1
config2
config3
data/
mydata
When you create a starkit/starpack from this directory structure, all the files get copied into it. You can reach them via:
#
# At the global level - otherwise [info script] does not return the
# proper directory (It is the location of "install.tcl" we need)
#
set scriptdir [file dirname [info script]]
#
# Now we have stored the script's location, we
# can manipulate it to reach our application directory
#
set appdir [file join $scriptdir ".." ".." "myapp"]
The procedure is really simple and straightforward:
- The user-interface lets the user select a directory
- All the files in the "virtual" directory myapp/ get copied to that selected directory
- Via the script "progman.tcl" (see Windows shell links - it is the script by Steve Cassidy) it will insert a new menu and the relevant items in the Windows Start menu.
You will need to customise the various bits and pieces but this is the gist of my installation script.
Note: For reasons unknown to me it sometimes takes a long time for it to finish copying the files out of the virtual directory. The files are there on disk, but the script is still processing the copy action.
Note: I have removed references to my specific software - not that is terribly confidential, but it is terribly irrelevant :).
Note: I use "mysomething" for all the things that need customisation (or removal).
package provide app-install 1.0
# install.tcl --
# "Install" myapp
#
# The procedure is very simple:
# - Allow the user to select a directory for installation
# - Copy the files from the starkit/myapp directory into the
# directory on disk
# - Create the new menu in the Start menu (assuming we are
# on Windows)
#
package require Tk
# fillCanvas --
# Fill the canvas with a picture and some text
#
# Arguments
# cnv Canvas widget
# cnv2 Second canvas widget
# Results
# None
# Side effects:
# Canvas filled
#
proc fillCanvas { cnv cnv2 } {
image create photo logo -file [file join [file dirname [info script]] mybanner.gif]
$cnv create image 0 0 -image logo -anchor nw
$cnv2 create text 20 5 -text "My app:" -anchor nw
$cnv2 create text 20 25 -text "Dedicated software" -anchor nw
$cnv2 create text 20 45 -text "for your eyes only" -anchor nw
$cnv2 create text 20 65 -text "NO WARRANTIES" -anchor nw
$cnv2 create text 20 85 -text "(c) Me" -anchor nw
}
# showInfo --
# Show some textual information
#
# Arguments
# None
# Results
# None
# Side effects:
# Message window with short information
#
proc showInfo {} {
tk_messageBox -parent . -icon info -title "My app - information" \
-message {
Whatever text you want to show
....
}
}
# selectDir --
# Select the directory for installation
#
# Arguments
# None
# Results
# None
# Side effects:
#
#
proc selectDir {} {
global installdir
set prevdir $installdir
set installdir [tk_chooseDirectory -initialdir $installdir -parent . \
-title "Select a directory to install into" -mustexist 0]
if { $installdir == "" } {
set installdir $prevdir
}
}
# copyFiles --
# Recursively copy files from one directory to the target,
# to avoid problems with existing directories etc.
#
# Arguments
# sourcedir Source directory
# targetdir Target directory
# Results
# None
#
proc copyFiles { sourcedir targetdir } {
foreach file [glob [file join $sourcedir *]] {
if { [file isdirectory $file] } {
set newsource $file
set newtarget [file join $targetdir [file tail $file]]
copyFiles $newsource $newtarget
} else {
file copy -force $file "$targetdir"
}
}
}
# installCourse --
# Install the course material
#
# Arguments
# None
# Results
# None
#
proc installApp {} {
global scriptdir
global installdir
set orgcursor [. cget -cursor]
. configure -cursor watch
set appdir [file join $scriptdir ".." ".." "myapp"]
#
# Check whether the installation directory is already there.
# If not, create it first. # Check if there is a file. If
# not, create a dummy file.
# The reason:
# - glob will complain otherwise
# - glob -nocomplain causes a different behaviour for
# directories with no subdirectories (at least on Windows XP)
#
if { ! [file exists $installdir] } {
file mkdir $installdir
}
set contents [glob -nocomplain [file join $installdir *]]
if { [llength $contents] == 0 } {
set dummyfile [open [file join $installdir dummy] "w"]
close $dummyfile
}
if { [file exists [file join $installdir waq]] } {
foreach file [glob [file join $installdir waq *]] {
file delete -force $file
}
}
foreach file [glob [file join $appdir *]] {
file copy -force $file $installdir
}
cd $installdir
#
# Add "My App" to the Start menu
#
file copy -force [file join $scriptdir "myapp.ico"] "."
set curdir [file join [pwd] bin]
set workdir [file normalize $curdir]
set progfile [file nativename [file join $curdir myapp1.exe]]
set iconfile [file nativename [file join $curdir "myapp.ico"]]
progman_creategroup "My app"
progman_additem "$progfile" \
"My app 1" "$iconfile" "$workdir"
progman_additem "[file nativename [file join $curdir myapp2.exe]]" \
"My app 2" "$iconfile" "$workdir"
tk_messageBox -message "Installation completed"
.cancel configure -text "Exit"
#exit
}
# main --
# Get the whole thing started
#
global scriptdir
global installdir
wm title . "MY APP"
wm iconbitmap . -default [file join [file dirname [info script]] "myapp.ico"]
canvas .canvas -height 90 -width 400 -background white
canvas .disclaim -height 120 -width 150
fillCanvas .canvas .disclaim
label .ltext -text "Install in:"
label .empty1 -text " "
label .empty2 -text " "
entry .edir -textvariable installdir
button .dirsel -text "Browse" -command selectDir -width 10
button .info -text "Info" -command showInfo -width 10
button .install -text "Install" -command installCourse -width 10
button .cancel -text "Cancel" -command exit -width 10
grid .canvas - - - -sticky ws
grid .ltext - - .disclaim -sticky ws -padx 10
grid .edir .dirsel - ^ -sticky ws -pady 4 -padx 10
grid .empty1 - - -
grid .install - .cancel .info -padx 10 -pady 10
#
# Some global stuff to take care of
#
set scriptdir [file dirname [info script]]
set installdir "C:/myapp"
source [file join [file dirname [info script]] "progman.tcl"]