Starpacks: Why and how to copy your own executable and launching the copied instance instead
Here's the latest standardized version of the above snipped:
################################################################################ # # Modul : autoclone.tcl # Date : 29.06.2007 # Purpose : copy the own program to a temporary folder and continue loading # the long-running program from there, to avoid locked and non- # updatable executables (starpacks under MS-Windows) # Author : M.Hoffmann # Remarks : A starkit/pack cannot copy itself with 'file copy' etc. without # first unmounting its own virtual file system # Programs locating profiles only in their own load path may fail; # they can use autoCloneOrgPath. # History : # 13.11.05 v1.0: first version derived from individual code in RECEIVE program # 11.05.07 v1.0: minor internal changes and updated wiki page # 28.06.07 v2.0: using suspendVFS instead of XCOPY; quit if no starpack; always # copy to temp folder to avoid security risc; translated source; # autoCloneOrgPath ################################################################################ package provide autoclone 2.0 ################################################################################ # see 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] } ################################################################################ # use proc to avoid cluttering the global namespace # proc autoClone {} { set myself [file normalize [info nameofexecutable]] proc autoCloneOrgPath {} " return [list $myself] " if {[string equal -nocase [lindex $::argv end] "--noautoclone"]} { # user don't want to use autoclone now or recursive call. Remove the # switch to keep things transparent for the later command line parsing. set ::argv [lreplace $::argv end end] set ::argc [llength $::argv] if {[string equal -nocase [lindex $::argv end-1] "--orgPath"]} { # remember the original load path, perhaps for loading configs from there proc autoCloneOrgPath {} " return [lindex $::argv end] " set ::argv [lreplace $::argv end-1 end] set ::argc [llength $::argv] } } else { set mytempP $::env(temp); # hm... no fallback yet for missing temp-var set mytemp [file normalize [file join $mytempP [file tail $myself]]] # v2.0: if we are not a starpack we can skip if {[string first $myself [file normalize [info script]]] != 0} { return } # no further action if called directly out of temp folder by the user if {[string compare $myself $mytemp]} { # alternative, old copy-method (piping 'copy' to 'cmd.exe' does not work for everyone): # catch {exec -- [auto_execok xcopy] [file nativename $myself] [file nativename $mytempP] /Y} if {![catch {suspendVFS [list file copy -force -- $myself $mytempP]}]} { # only ever continue if copy succeeds to avoid calling a trojan horse set ::argv [linsert $::argv 0 $mytemp] # attempt to use START not successfull yet (EXEC acts a bit strange...): # set ::argv [linsert $::argv 0 [auto_execok cmd] /c start \"[file nativename $mytemp]\"] # avoid recursion early if {[catch {eval exec -- [linsert $::argv end --orgPath $myself --noautoclone] &} rc]} { # our copy does not start; silently ignore the error and continue with this instance... } else { exit 0; # termine immediately as the launched copy takes control now! } } } } } # Attention: 'package require' automatically starts this code, so do it very early! 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 [L1 ] 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.