'''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'' ---- I'm currently testing the above linked solution, meanwhile, here's the standardized version of the above snipped: ################################################################################ # # Modul : autoclone.tcl # Stand : 13.11.2005 # Zweck : Kopieren des eigenen Programmes an eine temporäre Position und # Neustart von dort # Autor : M.Hoffmann # Hinweise : # # `Autoclone`-Verfahren zur Vermeidung blockierter .EXEs (Updates!): Programm # kopiert sich selbst in Temp-Position und lädt von dort. Leider kann ein # Starkit sich weder mittels 'file copy', noch mittels 'open/fcopy/get/put' # selbst kopieren, da dann die gesamte VFS-Struktur ausgepackt wird. # Es muss also ein externer Copy angestossen werden! (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). Daher # wird der externe Befehl XCOPY verwendet! # ACHTUNG: Ist das Paket eingebunden, wird das Verfahren automatisch über # das Paket initscript verwendet, es sei denn, der LETZTE Kommandozeilen- # Parameter lautet: --noautoclone # # ACHTUNG: Das Verfahren kann momentan nicht für Consol-Anwendungen (tclsh) # eingesetzt werden, nur für Tk-Programme. Evtl. kann dies mit START # umgangen werden. # # Historie : # 13.11.05 v1.0: als Paket aus RECEIVE übernommen (Schalter inkompatibel!) # ################################################################################ package provide autoclone 1.0 ################################################################################ # 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]]] # 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} # 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 for now only works with ''starpacks'' that use ''tclkit''... ---- Oh yeaah! Someone destroyed the page I'm just editing.... I have to retype everyting... ---- [Category Tclkit]