Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Executing external programs

by Silt (Novice)
on Feb 18, 2019 at 21:56 UTC ( #1230125=perlquestion: print w/replies, xml ) Need Help??

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

I am rather new to perl and so far only used it in the cmd and to read/write .txt files.
What I am trying to do, is to run a program and give it inputs. I tried:
use strict; use warnings; use 5.010; use IPC::Run qw(run); my $in = 'test text\n'; run ['C:\WINDOWS\system32\notepad.exe'], $in;
So I am trying to open notepad just to test it. It is in fact opening, but I want the perl code to write into the text box (I do not want to write a file and open it then). The perl code is also pausing until I close the window, so 'run()' is probably not the right function. 'system()' doesn't seem to be much better...
Also, how do I do other things like save a file after I wrote it the way noted above? 'Ctrl + S' won't work.
Just as a clarification, writing a file in notepad is just a test. My goal is not to write a file. I do know how to do that.

Thanks in advance!

Replies are listed 'Best First'.
Re: Executing external programs
by AnomalousMonk (Bishop) on Feb 19, 2019 at 00:20 UTC

    A modern operating system contains, among other things, an immense amount of code for the purpose of managing the event-driven GUIs that most fancy-schmancy modern applications use for graphically interfacing with... well, users. Using Perl (or any other language I'm aware of) to interface with these system drivers and thus to control an application is like trying to figure out a way to do neurosurgery by mounting scalpels on several dirigibles and then building a radio-control system to use them to operate on a patient in an operating theater set up in the middle of a football stadium.

    In other words, this sounds like an XY Problem. What do you really want to do?

    Give a man a fish:  <%-{-{-{-<

      Okay, let me try to rephrase my question then:
      I want to make (as an example) a program, that has access to hundreds of pictures. I want to apply certain effects to all of them with ''. Instead of going through one by one, I would write sth do do that for me. Open --> apply effect --> save --> repeat. GUI is entirely irrelevant.

      Does this example make it more clear?

        G'day Silt,

        "Does this example make it more clear?"

        Yes, that helps. I was about to search for a script, that I provided to someone here years ago, that embedded an editor in Tk. I don't need to do that now. :-)

        I don't have MSWin available nor am I familiar with ""; however, I can tell you how I would do this on my platform using an application that's also available on your platform.

        The application is called ImageMagick. It comes with a commandline tool called convert. I've used this many times, mainly for resizing images or converting images between one format and another; however, as its webpage says:

        "Use the convert program to convert between image formats as well as resize an image, blur, crop, despeckle, dither, draw on, flip, join, re-sample, and much more."

        So, perhaps one or more of its features equate to whatever "apply effect" means. If so, download an appropriate "Windows Binary Release" and write your code.

        You've not really provided sufficient information about your application to provide solid help with your code. If it's simply a one-off, quick-and-dirty script, you might get away with something like this:

        my $input_options = ... my $output_options = ... my @files = ... for my $file (@files) { `convert $input_options $file $output_options ${file}.out`; }

        Of course, if this is intended to be production-grade code, you'll want something more substantial.

        I did have a very quick look at I couldn't see any indication of a commandline tool but maybe you know of one: if so, you can probably use that with similar program logic.

        — Ken

        I want to apply certain effects to all of them with ''.

        Image::Magick, Imager, Gimp... or is this just another example? ;-)

        The more specific you are, the better we can help.

Re: Executing external programs
by haukex (Chancellor) on Feb 18, 2019 at 22:02 UTC
    I want the perl code to write into the text box (I do not want to write a file and open it then)

    If you want to display text to a user in a GUI with live updates, then attempting to use notepad.exe to do so is probably not the best way to do this. You probably want to look into UI toolkits like Tk or maybe Prima.

    Update: See also Perl GUI (2013).

      I don't mind how it is displayed. I just want to have a code that can change things in another program, i.e. write text in a text box and use tools inside that program.
      The goal is the execute a program with inputs that enters one in the field and then does sth with it. All automated.

        Well, there are e.g. GUI testing toolkits that can do things like that, but what the best method is also depends very much on which program you're trying to control?

Re: Executing external programs
by vr (Deacon) on Feb 19, 2019 at 12:24 UTC

    Though what others have said about XY problem and no need in neither nor any GUI to process images is true, here's an example, using Win32::GuiTest. Note, that in more general (or complex) case, you may have better chances with dedicated tools.

    I once had to automate a windows port of MacOS 9 (i.e. old, "Classic") app, which could only serve as a single file drop-target, a file at a time -- pinnacle of user-friendliness. No keyboard shortcuts, no CLI arguments processing (because MacOS 9), no AppleScript (because Windows) - worst of both worlds. It explains where from WM_DROPFILES is salvaged, below -- to show that "hard things are possible" -- but it's certainly overkill for such simple example. That said, it's probably fastest way to open a file in GUI. See MS docs for relevant data structures.

    It's for English (non-localized) Windows 7 (Server 2008, actually) mspaint version, your shortcuts may be different.

    use strict; use warnings; use feature 'say'; use Cwd 'cwd'; use File::Spec::Functions 'catfile'; use Win32::GuiTest qw( WaitWindow SendMessage AllocateVirtualBuffer WriteToVirtualBuffer FreeVirtualBuffer SetForegroundWindow SendKeys PushButton ); my $WM_DROPFILES = 0x233; my $pid = system 1, 'mspaint.exe'; my ( $h ) = WaitWindow( ' - Paint' ); for ( <*.jpg> ) { # I have a few JPGs in cwd. next if /flipped/; # Seen, skip. my $drop = pack 'LLLCCZ*x', 14, 0, 0, 0, 0, catfile cwd, $_; my $buf = AllocateVirtualBuffer( $h, length $drop ); WriteToVirtualBuffer( $buf, $drop ); SendMessage( $h, $WM_DROPFILES, $buf-> { ptr }, 0 ); FreeVirtualBuffer( $buf ); SetForegroundWindow( $h ); SendKeys( '%(hrov)' ); # Alt-Home, Rotate, Vertical_flip. # You like your pictures upside down, +don't you. SendKeys( '%(fa)' ); # Alt-File, Save As. WaitWindow( 'Save As' ); s/(?=.jpg$)/_flipped/; unlink; # Overwrite! Avoid needless idle quest +ions. SendKeys( $_, 1 ); PushButton( '&Save' ); sleep 1; # To prevent next file dropped when ap +p still # not sure if current file was saved. } SendKeys( '%{F4}' ); # Alt-F4, of course. No need to kill $ +pid. __END__
Re: Executing external programs
by bliako (Parson) on Feb 19, 2019 at 12:15 UTC

    That's my very personal opinion substantiated by my experience (but please feel free to criticise). I offer a Perl-based general solution at the end of my diatribe.

    Windows', as its name implies, selling point is having windows: i.e. interactive(*) sessions for the average user: click-click-file-open-click-confirm-click-yes. The user clicking is part of the Windows business model. Despite that, Windows are forced to provide a commandline which is intentionally a very hostile environment, after so many years of existing, for anyone to work. Possibly gone backwards from old dos5 functionality which was acceptable.

    Most users I have seen in similar situations have not dared to imagine that it could be possible to automate a menial and tedious task: the very definition of what the computer was meant to be and be doing for us. Hang on mad hacker, that's the wrong definition! The correct definition is that the computer was re-invented to mean "making money from users (and usually their lives worse too)". So, for me, it is twice a positive sign, to see anyone questioning the yoke modern computer companies fit on clients' necks and rise, to question it, albeit quite naively but that's not the issue because The Rubicon has been crossed and Rome awaits for you out there, and lot-a pizza.

    So, how can you achieve what you want: You use tools whose job is very specific and therefore do not require you to interact with them bar the initial setup. ImageMagick, as an example because other Monks here mentioned it - is one of them. Their logo is a wizard with a magic stick. And rarely has a logo been most appropriate. You give it an image in, you give it a task, e.g. "convert format" or "resize" or "reduce quality" (+50 more to chose from), you specify the output file and execute it from the command line. Any errors, e.g. input not found, are reported at the commandline and program exits with a numerical code which you can read or have your tools, programmatically read and act accordingly.

    So, now you know how to convert/resize one image without those pesky clicks-confirm-are-you-sure-file-open-file-browser-not-remembering-your-last-dir-navigate-to-obscure-dir-blah-blah. And you have a way to know whether the conversion succeeded (by the exit status/code). It's time to loop everything together over all the zillions of files you have. Each commandline has its own loop construct, Windows too: something like FOR %%parameter IN (*.jpg) DO magick-covnert ... But that's still primitive. You can create a batch file, a shell script which puts together everything. Another step in the right direction would, in my opinion and experience, be to move to linux. Pick a friendly distribution, say ubuntu or whatever, and use their commandline. But that's probably too drastic a step for one to take and you are too wet from crossing the Rubicon already, maybe leave that for another day. Plus, linux is not for everyone.

    But there is another option for you and that's Perl. There is already an image manipulation module for Perl (based on Magick, GD, possibly others, check Image::Magick, GD). So, first install Perl for Windows. Others here can suggest which distribution. And then write a Perl script which reads in the files (by specifying a filename pattern or a dir) you want to convert and converts them. Add a GUI with Tk so that your users do not feel way out of their comfort zone and you are done. Perl is also portable, so your script will work in Linux and Windows and OSX.

    Bottomline is: Perl is the easiest way to achieve what you want and there is no Tim Toady about that.

    (*) Interactive Experience: here is an alternative definition: I want users to be riveted to their keyboards and have their attention devoted to me, the OS, and my popups. Nothing should distract them from this. Also, users should not be able to predict if and when something will go wrong. The GUI's response should be as random as possible in order to project the fear of the unknown to the user. And pay even more attention to me, the OS, and my popups.

    bw, bliako

Re: Executing external programs
by karlgoethebier (Monsignor) on Feb 19, 2019 at 18:59 UTC

    PowerShell for the rescue? See here #8.

    Update: Fixed link.

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1230125]
Approved by haukex
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2020-01-27 11:41 GMT
Find Nodes?
    Voting Booth?