jdtoronto has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed monks,

I have a Windows application which is evolving very rapidly. So rapidly in fact that I am adding an autoupdate function to the software. Using Net::FTP I download a new copy of the software. What I would like to do is to be able to restart the program and have the new copy "take the place of" the original.

Any simple suggestions?


Replies are listed 'Best First'.
Re: Windows - have program replace itself
by waswas-fng (Curate) on Sep 27, 2004 at 16:47 UTC
    One other route you can take is to use PAR it enables you among other things to use and incluse large portions of your code from web servers or ftp servers. I think it can be setup to cache the includes locally and just update on change as well. It may be worth a look for you. From the relevent parts of the docs:

    On-demand library fetching With LWP installed, your can use remote PAR files: use PAR; use lib ''; use DBI; # always up to date! Modules are cached under $ENV{PAR_TEMP} Auto-updates with LWP::Simple::mirror Download only if modified Safe for offline use after the first time May use SIGNATURE to prevent DNS-spoofing Makes large-scale deployment a breeze Upgrades from a central location No installers needed

      I like this a lot (only with the signature features), but if you have a nice shiny GUI program (which PAR is GREAT at bundling), I'm wondering how easy it would be to funnel PAR connection errors up into happy-shiny-GUI well as whether one could produce "do want to upgrade, etc" type GUI's...

      If you wanted to upgrade a whole application this way, it would be fairly easy to have a simple shell with a go() method and have PAR download the entire application, then invoke the "go()". That way you would be free to completely rearchitect your app rather than fixing yourself to certain unbrekable interfaces.

      I'd probably just implement my own system though, with the launch.exe and a seperate goforthanddostuff.par ... and code my update interfaces around that. (preferably sftp with public keys that ship with the product, or something like that?)

Re: Windows - have program replace itself
by JediWizard (Deacon) on Sep 27, 2004 at 15:57 UTC

    Well if you are copying the new version over the old version, this should work:

    May the Force be with you

      IIRC, the problem is that Windows won't let you overwrite or delete a running program; that's why upgrades of running programs often require a reboot.

      Assuming exec works properly on Windows, one possible workaround would be to launch a second script which would download the first script, then re-execute it:

      # script 1 sub upgrade { exec('upgrade',$0,@ARGV) or die "exec failed! $!\n"; } # upgrade script download_new_version($ARGV[0]); exec(@ARGV) or die "exec failed! $!\n";
      gee, all of 9 characters, bit excessive?


      But serenely elegant if I may say so, thank you very much JediWizard I will give it a try :)


Re: Windows - have program replace itself
by jdtoronto (Prior) on Sep 27, 2004 at 19:47 UTC
    Okay folks, here is the results of playing with this idea:

    • Don't trust Windows, well to be specific, don't trust Perl in Windows to return what you think it should return. In my case I am developing in Komodo, so when I have Komodo run the programme, the value of $0 is something else altogether!
    • If I use PerlApp from Komodo (which I do anyway) then $0 returns a sensibble value. BUT JediWizard the exec($0); doesn't work as you would expect. But purely using exec("appname.exe"); works just fine.
    • Now, sgifford: I have packaged the app using PerlApp. This is some testing code:
      unlink 'appname_old.exe'; rename ( 'appname.exe', 'appname_old.exe'); use Win32; my $localdir = Win32::GetCwd(); print "My idea of a local directory: " . $localdir . "\n"; print "I think I am program: $0 \n"; use Net::FTP; my $ftp = Net::FTP->new( "", Timeout => 30, Debug => 0 ) or warn "Can't connect: $@\n"; $ftp->login( 'anonymous', 'guest') or die "Couldn't authenticate"; $ftp->cwd("/pub"); $ftp->type( "I" ); $ftp->get('appname.exe'); $ftp->quit; debug( "Quitting, restart programme please." ); exec("appname.exe");
      As you can see with the programme running I renamed the .exe file, and then copied a new file from the ftp server with the same name. So that all worked nicely.
    • Now waswas-fng suggests using PAR and running with parts of the programme remote. That's a neat idea. My application packages nicely with PAR and the idea of caching in-between is rather nice. I will lookinto it, thank you!
    • Now finally, Zero_Flop, thanks for the suggestion. Sadly, these folk are typical Windows users - ask them to open a command prompt and they go all glassy-eyed on you!
    Once again to all of you, thank you!


Re: Windows - have program replace itself
by mshipper (Novice) on Sep 27, 2004 at 21:13 UTC
    :) This is my first post, so Please be nice.

    Any ways here I go.
    1. copy the updated files into thier repsective locations.
    2. Run the new script in place of the old one
    exec 'scriptname', @ARGV;

    That is what I have for you...

      Welcome to the Monastery! We were all new once.

      Your suggestion is basically sound - and I knew that already. My problem was that I wanted the script to replace itself automatically. Thanks for your suggestion and enjoy your time here, if you find it only partly as worthwhile as I have then it will be an immensely rewarding experience for you.


Re: Windows - have program replace itself
by Zero_Flop (Pilgrim) on Sep 27, 2004 at 19:15 UTC
    Write a wrapper application that dls the current version, compares that to your existing version then launches the newest version.

    Actually you don't even have to do the compare, if it is from a secure trusted location. If it is a small script just have your wrapper dl then exec(file).
      you don't even have to compare, if it is from a secure trusted location
      Do you work for Microsoft?