newLISP Fan Club

Forum => newLISP and the O.S. => Topic started by: Cyril on September 06, 2010, 11:58:31 PM

Title: [SOLVED] Run an executable without opening console (Win32)
Post by: Cyril on September 06, 2010, 11:58:31 PM
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?
Title: Re: Q: Run an executable without opening console (Win32)
Post by: HPW on September 07, 2010, 02:12:09 AM
This older thread may help:

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



RUN - Run & Stop

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



Which has links to:

CMDOW - Commandline Window Utility [v1.4.3]

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



And:

CHP - Create Hidden Process

http://www.commandline.co.uk/chp/
Title: Re: Q: Run an executable without opening console (Win32)
Post by: Cyril on September 12, 2010, 02:05:54 PM
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.
Title: Re: [SOLVED] Run an executable without opening console (Win32)
Post by: Lutz on September 13, 2010, 07:12:39 AM
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



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.
Title: Re: [SOLVED] Run an executable without opening console (Win32)
Post by: Cyril on September 13, 2010, 08:11:03 AM
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 ... 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 this example (//http), and 32 was intended to mean NORMAL_PRIORITY_CLASS. But now I see (from this msdn page (//http)) 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.
Title: Re: [SOLVED] Run an executable without opening console (Win3
Post by: alex on April 23, 2015, 11:13:30 AM
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.