Page 1 of 1

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

Posted: Tue Sep 07, 2010 6:58 am
by 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?

Re: Q: Run an executable without opening console (Win32)

Posted: Tue Sep 07, 2010 9:12 am
by HPW
This older thread may help:
http://newlispfanclub.alh.net/forum/vie ... 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/

Re: Q: Run an executable without opening console (Win32)

Posted: Sun Sep 12, 2010 9:05 pm
by 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:

Code: Select all

(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.

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

Posted: Mon Sep 13, 2010 2:12 pm
by 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 ... 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.

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

Posted: Mon Sep 13, 2010 3:11 pm
by Cyril
Lutz wrote: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.
Lutz wrote: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).

Code: Select all

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

int main(void)
{
  printf("%d\n", sizeof(STARTUPINFO));
}

Have I miscalculated something?
Lutz wrote: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, and 32 was intended to mean NORMAL_PRIORITY_CLASS. But now I see (from 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).
Lutz wrote: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:

Code: Select all

(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.

Re: [SOLVED] Run an executable without opening console (Win3

Posted: Thu Apr 23, 2015 6:13 pm
by alex
Run a newLISP script from a Windows .js file without console window.
Full version:

Code: Select all

; // 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:

Code: Select all

; // 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.