'''Starpacks: Why and how to copy your own executable and launching the copied instance instead''' The Problem: Executables, like starpacks, are often called from single network shares from many users ''in parallel''. So the chance is good, that at least one user has an instance of that specific program running all the time. Now the administration wants to update that program. But this is not possible (at least) under MS-Windows, because each executable on disk, which has running instances active, is locked (such lock is invisible via ''net files''). The Solution: Each user has to launch his own ''private copy of the program''. But this must not lead to an distribution overhead: the program is still distributed only once to the network share, then each instance copies itself to a temporary position, runs from there and terminates quickly. The main executable is locked only for short load periods, so the program file on disk remains in a state where it can be overwritten (with retries, if required) for update purposes. Ideally, the per-user-copy of the program is stored in an temporary location which is periodically freed, so the harddisk will not be cluttered (for the above mentioned reasons, the 'user-copy' cannot delete itself while terminating...). Problems: I've discovered (anyone out there who can acknowledge this?) that a starpack cannot copy its own executable with tcl commands like ''file copy'' or a ''open/read/put/close''-sequence (because as a result always the whole directory structure gets unpacked in the destination). Maybe it has something to do with the underlaying '''VFS'''-Implementation... one must use an ''external'' copy/xcopy etc. instead which treats the .exe like any other disk file. Put the following sequence near the very top of your main starpack script: set myself [info nameofexecutable] set mytemp [file join $::env(temp) [file tail $myself]] if {[string compare -nocase $myself $mytemp]} { set mytempP $::env(temp) if {[catch {exec -- [auto_execok xcopy] [file nativename $myself] [file nativename $mytempP] /Y} rc]} { tk_messageBox -type ok -title Fehler:\ -message "Copy failed:\n\n$rc\n" -icon error exit 253 } if {[catch {eval exec -- $mytemp $argv &} rc]} { tk_messageBox -type ok -title Fehler:\ -message "Exec failed:\n\n$rc\n" -icon error exit 252 } exit 0 } ''See http://permalink.gmane.org/gmane.comp.lang.tcl.starkit/2537'' ---- Here's the latest standardized version of the above snipped: ################################################################################ # # Modul : autoclone.tcl # Stand : 27.06.2007 # Zweck : Kopieren des eigenen Programmes an eine temporäre Position und # starte neu von dort # Autor : M.Hoffmann # Hinweise : # # `Autoclone`-Verfahren zur Vermeidung blockierter .EXEs (Updates!): Das # Programm kopiert sich selbst in Temp-Position und lädt von dort. ACHTUNG: # Ein Starkit kann sich mittels 'file copy' oder 'open/fcopy/get/put' nur dann # selbst kopieren, wenn das VFS vorübergehend abgehängt, oder ein externes Tool # (z.B. XCOPY) verwendet wird (Warum XCOPY? Leider geht die Methode, cmd.exe # im Hintergrund zu starten und einen copy-befehl dorthin zu pipen, nicht, da # Benutzer teilweise kein Recht haben, cmd.exe zu starten). # # ACHTUNG: Ist dieses Paket eingebunden, wird das Verfahren automatisch über # das Paket initscript verwendet, es sei denn, der LETZTE Kommandozeilen- # Parameter lautet: --noautoclone. MOMENTAN NUR FÜR STARPACKS VERWENDBAR! # # Historie : # 13.11.05 v1.0: als Paket aus RECEIVE übernommen (Schalter inkompatibel!) # 11.05.07 v1.0: nur kosmetische Änderungen und Wiki-Update # 27.06.07 v2.0: Nutze suspendVFS statt XCOPY; Starpacks abfangen # ################################################################################ package provide autoclone 2.0 ################################################################################ # Siehe http://permalink.gmane.org/gmane.comp.lang.tcl.starkit/2537 # proc suspendVFS {code} { set me [info nameofexe] lassign [vfs::filesystem info $me] drv dbh vfs::filesystem unmount $me # unmounted, now run the code uplevel $code # Remount vfs::filesystem mount $me [list vfs::mk4::handler $dbh] } ################################################################################ # Prozedur zur Vermeidung globaler Variablen! # proc autoClone {} { if {[string equal -nocase [lindex $::argv end] "--noautoclone"]} { # Paket ist zwar eingebunden, aber wegen --noautoclone das # Verfahren nicht verwenden; also Schalter entfernen, um das # spätere Kommandozeilenparsing nicht zu stören. set ::argv [lreplace $::argv end end] set ::argc [llength $::argv] } else { set myself [file normalize [info nameofexecutable]] set mytempP $::env(temp); # Schwachpunkt: Umgebungsvar TEMP muss existieren! set mytemp [file normalize [file join $mytempP [file tail $myself]]] # v2.0: Nur Starpacks berücksichtigen if {[string first $myself [file normalize [info script]]] != 0} { return } # Abfangen: Aufruf bereits aus TempVerzeichnis if {[string compare $myself $mytemp]} { # Voraussetzung: Aufruf von XCOPY muss möglich sein! # catch {exec -- [auto_execok xcopy] [file nativename $myself] [file nativename $mytempP] /Y} # v2.0: internes Kopieren! catch {suspendVFS [list file copy -force -- $myself $mytempP]} # Falls Kopieren scheiterte, aber Ziel schon da war, ebenfalls fortfahren if {[file exists $mytemp]} { set ::argv [linsert $::argv 0 $mytemp] # Versuch mit START, bislang erfolglos (EXEC ist eigenwillig!): # set ::argv [linsert $::argv 0 [auto_execok cmd] /c start \"[file nativename $mytemp]\"] lappend ::argv --noautoclone # durch Angabe von --noautoclone hier Rekursion verhindern! if {[catch {eval exec -- $::argv &} rc]} { # Kopie ist aus irgendwelchen Gründen nicht aufrufbar; # Fehler ignorieren und aktuelle Instanz weiter verwenden! } else { exit 0; # sofort BEENDEN, da mit Kopie weitergearbeitet wird! } } } } } # ACHTUNG: Sofortige Ausführung durch PACKAGE REQUIRE! autoClone; ---- It should be mentioned that the code is intended for use by starpacks only, especially for GUI-Starpacks (problems with tclkitSH-version are likely, since the EXECd process eventually inherits some resources belonging to the console, so the EXECing process doesn't end...). ---- [EF] I was trying to point out that the locking mechanism that you describe here is the reason why my updater library [http://www.sics.se/~emmanuel/?Code%3Aupdater] does not work on Windows. However, the techniques that you are describing could be combined to the library in order to provide for binaries that update themselves when a new version appears at a known Internet location. ---- [Category Tclkit]