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

Hi all, I've been trying to get this to work for the past couple of weeks but it seems that it works fine in perl but it doesn't work in Tk. Here is my code:
my $title = "something"; my $executable = "C:/Users/Desktop/file.exe"; my $output = "C:/Users/Desktop"; my $outfile = "C:/Users/Desktop/$title.in"; open(OUTFILE,">$outfile") or die "Can't open output file $outfile\ +n"; print OUTFILE @array; close OUTFILE; my $msg = $mw->messageBox(-icon => "info", -type => "OK", -title => 'Save', -message => "File was +successfully saved."); chdir $output; system("$executable","$title",) == 0 or die "system $executable failed: $?";
When I run in this in perl, it works fine. However, in perl Tk, the system argument "$title" can't be read. The program freezes and when I stop the debugger, the executable file is opened but the argument is not passed. Is there any other way to go about this problem or can I write this in a different way? Any help would be appreciated, thanks in advance!

Replies are listed 'Best First'.
Re: Tk - system()
by zentara (Cardinal) on Aug 06, 2008 at 17:02 UTC
    Your example is confusing. Are you trying to write the system call to the OUTFILE filehandle? Make a better example please, and explain exactly what you want to occur.

    So it's hard to say from your limited code example, but you are probably running into a situation where system is blocking the Tk event loop. Tk (and all GUI's) run a thing called the event loop..... your new MainWindow; and MainLoop; statements are what start it. Once MainLoop gets called, a big loop starts running behind the scenes, doing everything you ask, on a schedule. When you put a while(1) loop in Tk, or a system call, it will hog the whole loop until it finishes (system returns).

    So...... you want to avoid system calls, unless they are in a piped open or somehow forked off. Since you are writing the results to an output file ( not collecting the results internally), you can fork off the system call, and let Tk keep running it's loop. So instead of system, fork and exec. Like:

    if(fork() == 0){ exec( "$executable $title" ) }
    I don't use windows, so there may be some special syntax you need to exec your command. See how to create independent process? and Perl Tk: opening a file in its original format for more ideas.

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      I am trying to create an input file from the GUI which is done by calling the OUTFILE filehandle. Then, I want to take this file and pass it to a .exe program which reads the title of the file and creates output files. This is where I call system() and try to output it to a specific directory. Before calling system, I had to specify the folder where the .exe file is if not, perl looks into the default directory and does nothing. I hope this helps. As for a better example, I wish I could give you one better but I'm having a hard time working it out.
        Here is something else I came up with after reading the docs you wrote:
        my $title = "something"; #title of the input file my $executable = "C:/Users/Desktop/file.exe"; # the .exe file where the input needs to be passed my $output = "C:/Users/Desktop"; # folder where the generated output files need to be located my $outfile = "C:/Users/Desktop/$title.in"; #location of the input file open(OUTFILE,">$outfile") or die "Can't open output file $outfile\ +n"; print OUTFILE @array; close OUTFILE; my $msg = $mw->messageBox(-icon => "info", -type => "OK", -title => 'Save', -message => "File was +successfully saved."); my @args = ("start",$executable,$title); for (@args) { # Apply smart-ish double quotes if (/ /) { $_ = qq{"$_"}; } }; chdir $output; #this command isn't working on Tk system(@args) == 0 or warn "Couldn't launch '$title' : $!/$?/$^E";
        This also works fine in perl but not in Tk. I think the problem here is that it doesn't locate the $output directory. I know that you chdir does nothing if the directory is not set properly. Is there another way of specifying the directory?