Running EXE files from within a Perl Script

I have written a piece of bespoke booking software in Perl on the Xampp implementation of Apache and I've encountered a problem running .EXE files.

My software ties in to the popular (in the UK) Sage Accounting package.  The company (Sage) supplies a set of develoment tools to read and write data to and from the accounts database but they only supply these tools in VB6 and VB.NET format.  I have Visual Studio and so used the VB6 version of the tools to produce an .EXE file which basically pulls out the next valid invoice number from the Sage accounts database.  It will do more, I just haven't got that far yet!

My problem is this, when I try to call my .EXE using the SYSTEM command in PERL, the browser tries to call the code but basically never returns, i.e. the bar at the bottom of the browser very very slowly inches forward but nothing further happens.

My .EXE file should create a file when it runs but doesn't so I assume that the .EXE is just not executing.  If I call my .EXE file via RUN, it all works fine.  I've tried to open Notepad using SYSTEM but exactly the same thing happens.

My software also uses Easy Software's HTML2PDF software to generate PDF files, the same executable can be run directly as a Windows application or in PERL using the SYSTEM command and it has always worked fine so I'm assuming that there's some problem with the EXE file that VB6 is generating - any help would be greatly appreciated.
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

Adam314Connect With a Mentor Commented:
You need to add some additional output to your vb program to help figure out where the problem is.

Suppose this is your program.  Add the new lines:

sub main()
    Dim fso As New FileSystemObject     'NEW
    fso.GetStandardStream(stdout).Write ("Starting...")    'NEW
    'Stuff your program does to initialize
    fso.GetStandardStream(stdout).Write ("Step 1...")    'NEW
    'Your program does some more stuff
    fso.GetStandardStream(stdout).Write ("Step 2...")    'NEW
    'Your program does some more stuff
    fso.GetStandardStream(stdout).Write ("Step 3...")    'NEW
    'Your program does some more stuff
    fso.GetStandardStream(stdout).Write ("Step 4...")    'NEW
    'Your program prints it's number
    fso.GetStandardStream(stdout).Write (number)
end sub

Then call the perl script from your perl script run by apache.
Kim RyanIT ConsultantCommented:
I would first try using the system call form a perl script that is run from the command line, not the browser. It should just be a simple one line script.

You could be facing problems with file permisions and groups, or restrictions on what commands you can run from a CGI (browser based) environment.
My .EXE file should create a file when it runs but doesn't... I'm assuming that there's some problem with the EXE file that VB6 is generating ...

I'm confused -- too many executable files...

Are you saying that you're running a VB6 executable file from a Perl system call, and this VB6 executable creates another executable file as its output?  If so, how is this output executable being called?

Does the executable produced by the VB6 executable run correctly from the command line?

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

frasierphilipsAuthor Commented:
The VB6 .EXE file is a small program that accesses the Sage accounting programs database (which is on the same computer) and retrieves the next available invoice number.

In order that my PERL based booking software can do its job (in this case to generate invoices) it needs to know what to start numbering the invoices from so it must run the .EXE file first but it can't because every time I try to call the EXE file my PERL script using the SYSTEM command, nothing happens other than the browser status bar slowly starting to build.

The .EXE runs perfectly if executed from the Command line.

The .EXE file retrieves the Invoice Number and saves it as a text file in the CGI-BIN directory for Perl to pick up, but this text file isn't being created when the EXE is called from within the PERL script so I'm assuming the EXE isn't executing at all.

I can't get Notepad.exe to run from my script either (I tried this as a simple test) however I use a program called HTML2PDF.EXE which creates PDF files and this runs perfectly from my PERL script using the SYSTEM command.
notepad.exe won't work as it will be trying to invoke that on the webserver, not on your PC.

What user are you running the vb6 exe from command line?
frasierphilipsAuthor Commented:
Because I'm still developing the software, the XAMPP/APACHE is running on my local machine, not over a network, so it's all logged onto the same account.  What I don't understand, and none of the posts have addressed this, my script is running another EXE file, part of the HTML2PDF package, perfectly fine - this is a program we bought in, you install it on your Windows based system (it creates registry keys etc) then all I had to do to get it to run on the web server was copy the exe file HTMLDOC.EXE into the CGI-BIN folder and call it from the SYSTEM command - it worked perfectly first time, I didn't have to modify any Apache permissions, it just worked.  I've checked its permissions in Windows and they are no different to any other Windows file which is why I wonder if it's the structure of the EXE being created by VB6 that's the problem.
I'm not sure if this will help, but I have often found that problematic system calls to executables in Windows can be solved by using the "start" command and quoting.  For example:

system ("start \"$ENV{HOMEDRIVE}\\Program Files\\internet explorer\\iexplore\.exe\" \"$htmlfile\"");
system ("start wordpad.exe \"$txtfile\"");
system ("start \"$ENV{PROGRAMFILES}\\IrfanView\\i_view32\" $pic");
frasierphilipsAuthor Commented:
Thanks, I tried that.  What I'm beginning to think is that because the VB6 EXE file is actually part of a Form object OnLoad event, when the EXE file is executed by Apache, the EXE tries to invoke a GUI which because of the scope of it's execution, it is unable to do so it just sits there waiting for the GUI to kick in.  Sage have suggested excuting the code as part of a VB.NET console object so I'm gonna give that a try.
Try changing your VB6 startup to be "sub main" instead of "form main".  I don't remember exactly where this option is, but I think it's in the project properties.
Then create a module (I think it's insert -> Module), create a sub main, and have all your code in there (or in other functions.., but no forms).
Then remove all forms from your application.
Recreate the exe file.
Try running this new exe file.

You're not calling the perl script (which contains your .exe call) from  the webserver (apache)? Are you?
That cannot work with .exe file which require/have a GUI like notepad.exe or ie.exe, obviously ...
frasierphilipsAuthor Commented:
I tried Adam314's suggestion and it has stopped the browser 'stalling' so the code seems to be executing HOWEVER it's still not creating a file in the cgi-bin folder.  I wonder if this is a permission problem, i.e. the .EXE file isn't allow to save a file when executed by Apache.  As before, it does create the file if run from Windows.  The invoice number is 13635 - is it possible to send thiis as a return value from the EXE file?
Normally, a script will NOT have write access to your cgi-bin folder.  If you need to have your script write to a file, you should create a directory for that - it is not generally good security practices to allow a script to write to the cgi-bin folder.

If you don't want the EXE to create a file - you just need the number, you can have the VB6 app "print" the number.  This will go to the programs STDOUT.
Then, in perl, you can read that data using backticks instead of system.
If you had:
You would put:
    my $invoice_number = `myprogram.exe`;
    chomp($invoice_number);     #to remove the newline

frasierphilipsAuthor Commented:
I changed the location for the file write to another folder (c:\xampp\xampp\htdocs\tmp) and it still didn't create a file.  

Also, I knew there was a reason why I steered clear of VB!  Is there any simple way of writing to STDOUT?  The simplest code I could find is:-

    Dim fso As New FileSystemObject
    fso.GetStandardStream(stdout).Write (Text)

The .EXE file can be created without error, but nothing turns up at the Perl end after the .EXE has supposedly executed.
Seems like a lot to write to stdout... but i guess vb is designed more for GUI type applications.  I don't use vb very often though, and don't know an easier way.

The user running apache will probably not be the same user that you use to log in.  If you want the program to be able to write to a file when running in apache, you have to give the apache user permission to do that.

When you run the vb exe program from the command line, does it create a file?  Do you get any output?
frasierphilipsAuthor Commented:
To be honest, I don't even know if it is running, it doesn't hang anymore but also, I can't get anything to turn up at the Perl end and no file is created.  A few posts earlier, I mentioned a program we bought in called HTML2PDF.  It's a pretty solid program that turns HTML files into PDFs.  The reason I keep mentioning it is because it comes with a standard Windows installer and can be run from the Windows command line HOWEVER if you want to use it on a webserver (such as Apache running in Windows) you simply copy the executeable into the CGI-BIN folder and hey presto it just works.  I set it to create PDFs in the folder C:\XAMPP\XAMPP\HTDOCS\PDFS and it does so.  It didn't need any special permission changes or anything like and it's invoked via the PERL SYSTEM call.  

I'm starting to think that VB6 isn't up to this, I've got a copy of VB.NET coming tomorrow.
I don't think will make it any easier.  If you've never programmed in .net, there is a learning curve, as .net is very different from classic vb.

Try this:
copy your vb exe program to your cgi-bin folder
go to a command prompt
change to your cgi-bin folder (eg: cd \inetpub\wwwroot\cgi-bin)
Try to run your exe program: programname.exe

Do you get any output?
Is the file it is supposed to generate created?
Any error messages?

frasierphilipsAuthor Commented:
No error messages, it worked perfectly.
By worked perfectly, it created the file and produced the desired output?

Is there anything in your logs that helps - either your apache log or the sage log?

Does your script (or any of it's libraries (eg: sage)) use any environement variables?
If so, you will have to have these set in your apache environment - they most likely will not be.

When checking the database, are there any permission required?  How does it determine this?
If it uses your login name, this will be different when running from within apache.

You might want to add some debugging output to your vb exe program.
For example, have it print a message every so often about what it is doing.
Then, when run from your webserver, you will get some output to help you figure out what is causing the problem.
frasierphilipsAuthor Commented:
I think that's the big problem, I actually don't know what's hapeening with the VB script. - is it executing or not?  I'm now pretty proficient with Perl but on a need-to-know basis with VB.  As far as I can determine, and it's backed up by some of the other postings on here, I can't have anything in my VB that requires screen output to a Windows object such as a form because if I do, the EXE file it produces can't be run by Apache because it invokes the GUI.

This leads onto trying to invoke the Windows console to capture any output but apparently this is a very invloved process on VB6 whereas I'm lead to believe that VB.NET actually has a console object.

I think what I'll do first is see if VB6 has some way of beeping the PC speaker and add that to the start of the code, at least if the speaker beeps I'll know if the EXE is running.
frasierphilipsAuthor Commented:
I added a beep to the VB code and recompiled it and lo and behold, a beep when you clicked the link to the Perl calling script.  So the EXE is running, it just isn't passing a value back or creating a file.
We really, really need to know the behavior of this VB6 program when run from the command line -- a full and complete answer, not just "it works perfectly"...

Is there a GUI invoked when it's executed from the command line?  If there is, there will be when Perl calls it, too, if there isn't, there won't be.

Is a file produced by the VB6 program when it's run from the command line?

Is there any pertinent information in your Apache error logs?  How about the Window's event logs (run eventvwr from the command line)?

Is there a reason you must use a VB script to perform this step in your program?  Can't Perl do it?
frasierphilipsAuthor Commented:
There is no GUI - I have gone to great lengths to make sure there are no components in the VB6 script that would invoke the GUI and the code is run from a SUB MAIN not a FORM.

The file is produced when run from the command line - i.e. it works perfectly

There is no info in the Apache log.

I've got to use VB because Sage (which won't mean much to you if you aren't in the UK, but they are a VERY big deal in accounting software in this country, probably 90%+ of businesses that use computerised accounts use their software)  only supply the modules to integrate third party software with theirs in VB6 and VB.NET formats.

And to reiterate my last comment, when I added a BEEP command to the script, there is a beep when the Perl script link calling the EXE is clicked so the EXE is running, it simply isn't creating the file or passing back a return value.
Nothing in the Windows event logs, either?

What is the reurn code of the system command ($status = $?; after the system call)?

What if you explicitly re-direct output?  Something like:

system("VB6_command >stndout.txt  2>stnderr.txt");

What happens if you use the exec() command, rather than the system() command?

Call the DOS set command via a sytem call:

system("set >system_env.txt");

and compare it to the output of running the set command from the DOS command line.  are there any differences between the two outputs?
frasierphilipsAuthor Commented:
Will try your suggestion, SYSTEM returns 0 after call
frasierphilipsAuthor Commented:
Problem solved - believe it or not (and I can't think why I didn't spot this) my home PC is running VISTA Ultimate - it was stopping the script from executing.  When I tried it on the XP machine at work, hey presto!  
All Courses

From novice to tech pro — start learning today.