[SOLVED] Run an executable without opening console (Win32)

Started by Cyril, September 06, 2010, 11:58:31 PM

Previous topic - Next topic

Cyril

Is it possible to run an external program (ex. notepad.exe) from newlisp on Win32, not opening a console window, and wait for it to finish? Both (! "notepad.exe") and (exec "notepad.exe") run cmd.exe first and therefore create a console window. On the other hand, (process "notepad.exe") runs notepad.exe directly, and doesn't wait for notepad to finish. And there is no wait-pid in Win32. Can I have both, please?
With newLISP you can grow your lists from the right side!

HPW

This older thread may help:

http://newlispfanclub.alh.net/forum/viewtopic.php?f=2&t=2591">http://newlispfanclub.alh.net/forum/vie ... f=2&t=2591">http://newlispfanclub.alh.net/forum/viewtopic.php?f=2&t=2591



RUN - Run & Stop

http://www.turtle.dds.nl/run/">http://www.turtle.dds.nl/run/



Which has links to:

CMDOW - Commandline Window Utility [v1.4.3]

http://www.commandline.co.uk/cmdow/">http://www.commandline.co.uk/cmdow/



And:

CHP - Create Hidden Process

http://www.commandline.co.uk/chp/">http://www.commandline.co.uk/chp/
Hans-Peter

Cyril

Thanks, HPW! The solutions from the thread you mentioned aren't applicable to my problem directly, but they have inspired me to read the source, and to write some newlisp code based on them. Here it is:


(import "kernel32" "CreateProcessA")
(import "kernel32" "WaitForSingleObject")
(import "kernel32" "CloseHandle")

(define (run-and-wait command-line , si pi ph th)
    (setq si (pack "ld n64" 68))
    (setq pi (pack "n16"))
    (CreateProcessA 0 command-line 0 0 0 32 0 0 si pi)
    (map set '(ph th) (unpack "ld ld" pi))
    (WaitForSingleObject ph 0xFFFFFFFF)
    (CloseHandle ph)
    (CloseHandle th))

(run-and-wait "notepad.exe")

(exit)


The function run-and-wait runs a command and wait for it to finish, just like built-in (! "notepad.exe") but not creating an additional console window.
With newLISP you can grow your lists from the right side!

Lutz

In the next version an addtional "process creation flags" -parameter can be used on Windows versions of newLISP.



See the development/inprogress/newlisp-10.2.15.tgz



While coding this, the following details in run-and-wait.lsp caught my attention: Shouldn't the size for STARTUPINFO si be 72? I believe the total structure size including the si.cb field should be taken? In any case having it bigger probably doesn't make a difference;si. cb now as sizeof(STARTUPINFO).



As flags you specify 32 or 0x00000020 for dwCreationFlags, couldn't find that flag on this page:  



http://msdn.microsoft.com/en-us/library/ms684863%28v=VS.85%29.aspx">http://msdn.microsoft.com/en-us/library ... 85%29.aspx">http://msdn.microsoft.com/en-us/library/ms684863%28v=VS.85%29.aspx



but found 0x00000200 (512) for CREATE_NEW_PROCESS_GROUP. If this is what you meant, we could take this as the default value or just leave it as zero.



You can find the function p_system() in nl-filesys.c starting at line 957.



I any case thanks for coming up with an solution, this helped to code the function quickly in C.



ps: also on my system XP running in VirtualBox on Mac OS X, there is no difference running the old or new '!' function, althoigh others are observing this. No additional command shell, except for the one running the calling newLISP instance, is created no matter what function or flags.

Cyril

Quote from: "Lutz"In the next version an addtional "process creation flags" -parameter can be used on Windows versions of newLISP.


My problem was not wrong parameters, but the return value. What is the "pid" returned, and how can one use it? In Linux, it can be passed to wait-pid, but in Win32 there is no such function, and WaitForSingleObject system call accepts process handle instead. My example was written with the single goal to obtain this process handle.


Quote from: "Lutz"While coding this, the following details in run-and-wait.lsp caught my attention: Shouldn't the size for STARTUPINFO si be 72? I believe the total structure size including the si.cb field should be taken? In any case having it bigger probably doesn't make a difference;si. cb now as sizeof(STARTUPINFO).


sizeof(STARTUPINFO) is 68 on my system, and (pack "ld n64" 68) seems to be 68 bytes in total (4 bytes for si.cb and 64 zeros).


#include <stdio.h>
#include <windows.h>

int main(void)
{
  printf("%dn", sizeof(STARTUPINFO));
}



Have I miscalculated something?


Quote from: "Lutz"As flags you specify 32 or 0x00000020 for dwCreationFlags, couldn't find that flag on this page:



http://msdn.microsoft.com/en-us/library">http://msdn.microsoft.com/en-us/library ... 85%29.aspx



but found 0x00000200 (512) for CREATE_NEW_PROCESS_GROUP. If this is what you meant, we could take this as the default value or just leave it as zero.


I have modeled my code after http://www.chami.com/tips/delphi/122096D.html">this example, and 32 was intended to mean NORMAL_PRIORITY_CLASS. But now I see (from http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx">this msdn page) that this is the default, and yes, therefore this parameter may be safely replaced to zero. Thanks, I'll do this (for the sake of simplicity).


Quote from: "Lutz"ps: also on my system XP running in VirtualBox on Mac OS X, there is no difference running the old or new '!' function, althoigh others are observing this. No additional command shell, except for the one running the calling newLISP instance, is created no matter what function or flags.


I do close the initial command shell (by standard trick of using FreeConsole imported from kernel32) at the very first lines of my script, and then ! re-creates it. Try this example:


(import "kernel32" "FreeConsole")
(FreeConsole)

(sleep 5000) ; no console window while sleeping

(! "notepad.exe") ; two windows are created: cmd.exe and notepad.exe

(exit)

This is the problem I try to avoid.
With newLISP you can grow your lists from the right side!

alex

Run a newLISP script from a Windows .js file without console window.

Full version:
; // Posted by alex from newlisp.org
; var ScriptName = WScript.ScriptFullName;
; var App = "newlisp.exe " + ScriptName;
; var objArgs = WScript.Arguments;
; for (i = 0; i < objArgs.length; i++) { App = App +" "" + objArgs(i) + """; }
; var oShell = WScript.CreateObject ("Wscript.Shell");
; oShell.Run(App, 0, false); /*
# begin newlisp-program
(device (open "Hello!.txt" "write"))
(print "Hello!")
(close (device))
(exit)
# end newlisp-program
; */


Short version:
; // Posted by alex from newlisp.org
; var A = "newlisp.exe " + WScript.ScriptFullName; var R = WScript.Arguments; for (i = 0; i < R.length; i++) { A = A +" "" + R(i) + """; }; WScript.CreateObject("Wscript.Shell").Run(A, 0, false); /*
# begin newlisp-program
(device (open "Hello!.txt" "write"))
(print "Hello!")
(close (device))
(exit)
# end newlisp-program
; */


Tested in Windows7, but must work(I think) with Windows2000 and later.