Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Restarting a Perl script on Windows 10

by petro4213 (Acolyte)
on Sep 20, 2019 at 10:06 UTC ( [id://11106428]=perlquestion: print w/replies, xml ) Need Help??

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

I have a Perl script with a GUI that restarts itself, if I press a button in the GUI. This is done through this simple call in the callback of the button:
exec( $pathToMyself );
This works fine on Windows 7. But on Windows 10, the script ends (and the GUI disappears), but it doesn't restart, unless I go to the command window, which I used to initially call the script, and press the Enter key there.
I don't like this behavior. Can anyone explain, where this comes from or give me a hint, if there's something I can do from the Perl side to restart my script without having to press Enter?
Thanks a lot!

Here's a simple reproducible example:

use Tk; use strict; my $pathToMyself = $0; my $mw = MainWindow->new(); my $bt = $mw->Button(-text=>"Restart", -command=>\&restartMe)->pack(); MainLoop; sub restartMe { print "Restarting $pathToMyself...\n"; exec( $pathToMyself ); }

Replies are listed 'Best First'.
Re: Restarting a Perl script on Windows 10
by pryrt (Abbot) on Sep 20, 2019 at 13:44 UTC

    Since no one has given an answer yet, I'll chime in with confirmation. I see the same thing on Windows 10, even when not using Tk. I ended up spawning $^X, $pathToMyself because my perl association isn't working (new computer, apparently hadn't used my assoc yet), but I get the same results -- I have to hit ENTER to actual enter the new instance.

    #!/usr/bin/env perl use warnings; use strict; my $pathToMyself = $0; local $, = "\n\t* "; local $\ = $/; print "\t".$^X, $0, @ARGV; restartMe() unless @ARGV; sub restartMe { print "Restarting $pathToMyself...\n"; #exec( $^X, $pathToMyself ) or die "couldn't exec $pathToMyself: $ +!"; #system(1, $^X, $pathToMyself, "don't Restart", "final" ); exit; #system(1, "cmd.exe", "/c", $^X, $pathToMyself, "final"); exit; exec("cmd.exe", "/c", $^X, $pathToMyself, "final") or die "couldn +'t exec $pathToMyself: $!"; }

    As you can see from my commented lines, I tried various combinations of exec and system, both with and without an explicit cmd.exe interpreter. I don't know what's going on, but I can definitely confirm it.

    edit: fixed my association to be perl "%1" %*, so it would run without the cmd or $^X, but no change in behavior

    system(1, $pathToMyself, "don't Restart", "final" ); exit; #exec( $pathToMyself, "final" ) or die "couldn't exec $pathToMyse +lf: $!"; # can't exec ___: Exec format error -- because this runs wit +hout the cmd.exe overhead, so it doesn't try the association for .pl +file
      I do not have a solution, but I may have narrowed the problem for you. I ran your example (without updates) on Windows 7. The second instance does run, but does not return to the command window until I type a return. I suspect (without any real reason) that the problem is related to terminal I/O. I modified you program to avoid it (Removed both print statements). In order to verify that the second instance actually ran, I added an open statement to create a file. The resulting program runs to normal completion. The presence of the zero-length file in my current directory verifies that the second instance ran. I have no idea if this applies to windows 10 or if it will be of any help with the original Tk problem.
      #!/usr/bin/env perl use warnings; use strict; my $pathToMyself = $0; local $, = "\n\t* "; local $\ = $/; #print "\t".$^X, $0, @ARGV; restartMe() unless @ARGV; open my $foo, '>', 'UniqFileName.___'; # Look for file in CWD sub restartMe { # print "Restarting $pathToMyself...\n"; #exec( $^X, $pathToMyself ) or die "couldn't exec $pathToMyself: $ +!"; #system(1, $^X, $pathToMyself, "don't Restart", "final" ); exit; #system(1, "cmd.exe", "/c", $^X, $pathToMyself, "final"); exit; exec("cmd.exe", "/c", $^X, $pathToMyself, "final") or die "couldn +'t exec $pathToMyself: $!"; }
      Bill

        BillKSmith, interestingly, if I try to write anything to the UniqFileName.___, it goes back to needing the ENTER. For example:

        #!/usr/bin/env perl # started from https://perlmonks.org/?node_id=11106496 => BillKSmith's + version... # as use warnings; use strict; my $pathToMyself = $0; local $, = "\n\t* "; local $\ = $/; open our $foo, '>>', 'UniqFileName.___'; # Look for file in CWD print {$foo} $^X, "0 = $0", "ARGV", @ARGV; restartMe() unless @ARGV and $ARGV[0]>1; sub restartMe { $ARGV[0] ||= 0; print {$foo} "Restarting $pathToMyself 1+$ARGV[0]...\n"; exec("cmd.exe", "/c", $^X, $pathToMyself, 1+$ARGV[0]) or die "cou +ldn't exec $pathToMyself: $!"; }

        If I run that code using perl 11106428-11106496.pl or using my association at the command line using 11106428-11106496.pl, I get:

        c:\usr\local\apps\berrybrew\perls\system\perl\bin\perl.exe
        	* 0 = 11106428-11106496.pl
        	* ARGV
        Restarting 11106428-11106496.pl 1+0...
        

        Then if I hit ENTER, I get the next block, and ENTER again I get the final block:

        c:\usr\local\apps\berrybrew\perls\system\perl\bin\perl.exe
        	* 0 = 11106428-11106496.pl
        	* ARGV
        	* 1
        Restarting 11106428-11106496.pl 1+1...
        
        c:\usr\local\apps\berrybrew\perls\system\perl\bin\perl.exe
        	* 0 = 11106428-11106496.pl
        	* ARGV
        	* 2
        

        However, if I run by double-clicking on the script in Explorer, then it generates all three blocks in the UniqFileName.___ right away. With that result, and jcb's suggestion of wperl, wperl 11106428-11106496.pl (from the command line) will also generate all three blocks without typing ENTER. (Seeing jcb's wperl mention reminded me that wperl is supposed to launch without needing the cmd.exe window)

        Taking that lesson learned: if I use the original code, if I double-click on the file, it opens up the single cmd.exe for STDOUT, but properly respawns other than that. And from the command-line, if I run with wperl 11106428.pl instead of perl 11106428.pl, then the Tk properly respawns every time (and the STDOUT is lost to wperl's absorption of such.

        So, for petro4213, you might want to have a special extension (like .wpl for windows-perl, or .tkpl or .pltk for perl-with-tk), and use an association with wperl.exe rather than perl.exe for that/those extension(s). (If you do, you'll want to make sure you never write to STDOUT or STDERR... or redirect those to some logfile.)

        Hi, thanks for your hints.

        Your suggestion with Win32::Unicode::Process restarts the program without having to press Enter, but doesn't exit the original instance.

        The keys in the registry are the same as on my Windows 7 machine:
        CompletionChar 0x00000009 DefaultColor 0x00000000 EnableExtensions 0x00000001 PathCompletionChar 0x00000009
        I don't understand what you mean with system_detached
Re: Restarting a Perl script on Windows 10
by NetWallah (Canon) on Sep 20, 2019 at 17:48 UTC
    I was able to get this to start without <enter>:
    exec("wmic","process","call","create", "CommandLine='cmd /k $pathToMys +elf'" );
    But it keeps an annoying empty cmd window hanging around.

                    "From there to here, from here to there, funny things are everywhere." -- Dr. Seuss

      I am happy to say that I currently avoid Windows, but your code gives me an idea or three:

      exec(qw/wmic process call create/ => "CommandLine='$pathToMyself'" ); +# if Perl scripts are associated to perl exec(qw/wmic process call create/ => "CommandLine='perl $pathToMyself' +" ); # if perl.exe is in %PATH% exec(qw/wmic process call create/ => "CommandLine='wperl $pathToMyself +'" ); # if wperl.exe is in %PATH%

      These of course are completely non-portable in typical Microsoft style, so if you want your script to be generally usable, try adding this before one of the above:

      unless ($^O eq 'MSWin32') { exec( $pathToMyself ) }

      Really the best answer is probably to get a better operating system...

        "Really the best answer is probably to get a better operating system..."

        As nice as that sounds, there are all number of reasons why this may not be desirable, feasible, or even possible for some people.

        Personally, the only time I use Windows is when I'm developing berrybrew. I've got a few VMs configured for that. So realistically, I only use Windows to develop software that I don't even use :)

        ...that's not entirely accurate. I use my Test::BrewBuild CI automation against Perl instances running under berrybrew on a Windows system that all it does is listen for incoming test run requests. I have a VM set up with Perlbrew as well for the exact same purpose. All of my distributions (the cross-platform ones) are automatically tested against both Windows and Unix over the network, across at least 10 versions of Perl before I do a CPAN release.

        Thanks! This works fine.! :-)

        The only ugly thing is, that it not only restarts my program, but it also creates a new command window. Any idea on how to get rid of this or at least get it minimized?
        I initially missed the option with the command line using wperl. This works well, because it hides the new command window.
        Really the best answer is probably to get a better operating system...

        Windows 10 seems like spyware posing as an operating system. macOS has the same smell but they disguise it as cloud services (lol). I had to implement 2 firewalls to extinguish the constant creepshow of unintended and unknown outbound network connections sending god knows what, encrypted, to the criminal minds at Apple, Inc. Thank Linus for Linux!

        The solution

        exec(qw/wmic process call create/ => "CommandLine='wperl $pathToMyself'");

        works fine, as long as the script to call (pointed to by $pathToMyself) doesn't require additional command line parameters.

        I know, that this is not a Perl issue, but would you have a solution on how to add command line parameters to this call? I must admit that I don't understand the wmic docs...

        Really the best answer is probably to get a better operating system...

        oh noes my fork is not a knife. My car won't start. Better get a new one. Probably. New bathwater; New baby. No logic by job.

      Duh cmd /k /K Run Command and then return to the CMD prompt. This is useful for testing, to examine variables
Re: Restarting a Perl script on Windows 10
by stevieb (Canon) on Sep 20, 2019 at 17:02 UTC

    I did a little testing of my own here... what I found is that I experience the whole Tk window disappears until I hit Enter if I start the application from the CLI window directly.

    If I double-click on the script within the UI, the Tk window re-appears properly without having to hit enter.

    I've got to run so I can't test further right now, but I do know that win10 had some new registry settings added related to the cmd.exe program, so that might be worth having a look at. I'm absolutely unsure about this, but if it is a registry setting, you may even be able to have your script modify it on the fly using Win32::Registry (my experiences with Windows is that changing anything requires reloading whatever you're trying to modify though).

      Same for me: If I start it by a double click in the UI, I can restart it over and over without having to press Enter.

      That's at least a workaround, because I usually have to specify command line options. But if I put them in a batch file, restarting still works, if I double-click the batch file.

      Thanks a lot.
Re: Restarting a Perl script on Windows 10
by Anonymous Monk on Sep 21, 2019 at 11:02 UTC
    ?What do you have for ?
    perl -V:sh

    ?What do you get with

    sub exec { system 1, @_; exit 0; }
      For perl -V:sh I get
      sh='cmd /x /c'
      on both machines (Win10 and Win7).

      Your suggestion with the system and exit calls works once, but if I try to restart the restarted instance of the program, I need to press the Enter key again :-(
        Are you mouse clicking on the cmd window? Is your mouse double clicking? So you click restart and the double click clicks cmd thus entering quickedit mode?
Re: Restarting a Perl script on Windows 10
by Anonymous Monk on Sep 22, 2019 at 08:21 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11106428]
Approved by marto
Front-paged by pryrt
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-19 05:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found