Archive: ExecCmd plug-in


ExecCmd plug-in
Long ago Joost Verburg wrote about WM_CHAR possibility for console windows, this appeared again few days ago http://forums.winamp.com/showthread....30#post1846930 , so I updated ExecDos and suddenly found mysqladmin and gnupg problems solved :) New ExecCmd attached to this post. 'Test' dll version allows to see console window.


Good news: wiki page; 'ComSpec /C' now appeares at the beginning of the command line (so you don't need to use it in script), but do not forget quotes; /TIMEOUT bug fixed; new /TEST key - displays console window (for debugging); tested on XP - 2003.
Bad news - Win98 problem, console window appeares with toolbar, so I need to find another way to launch application on old systems or to write enhanced code for child console search.


ExecCmd close immediately
I have the following procedure to execute in background with execcmd.

ExecCmd::exec /SYNC '"$TEMP\nativeImage\ngen.exe" install "$INSTDIR\xxx.exe"'

When I use the same cmd-line with ExecWait it works perfectly, but the cmd-window appears. How can I use ExecCmd to generate native images in background, withour cmd-window?

When I use /TEST the window appears but only for a 10th of second. When I add "> log.log" to the cmd-line, the is created but it is empty.

Any suggestion?

thx


Might be better to use ExecDos in your situation. And no SYNC option, /ASYNC only, but this require ExecDos::wait after this. For simple situations (short calls) just remove this option at all.


Thanks a lot.

Now it works as I want.


Is there any way to echo the command line program's standard output to the installer log?


http://nsis.sourceforge.net/ExecDos_plug-in offers a lot of output targets.


how can i run this command in cmd.exe:

sfc /purgecache


ExecDos::exec `sfc /purgecache`
Pop $R0 # exit code

Stu


Hmm I have found that ExecDos doesn't push blank lines to the stack with /TOSTACK. Also if the program outputs an empty string (or in effect, no text) then you also don't get anything on the stack.

This is usually ok but when you need to check this value this is a problem.

Stu


Yes, Stu, this is 'by design'.

/* supress empty lines */
if(iStack > 0)
...
I can agree that empty lines should be pushed to stack as well, but I have not ideas what to push if no output at all (what means 'empty string'?). If no output from application, exit code can help, not 'empty string'.

In other words, if the program is a command line application and outputs nothing, maybe we should push an empty string.

Stu


This case there is no difference with the only "\n" output. Just keep stack empty and check Pop error.
Pops a string off of the stack into user variable $x. If the stack is empty, the error flag will be set.


Erm i have a noob qn (just learnt NSIS yesterday), ExecCmd doesn't seem to work for paths with spaces in them.

E.g. $PROGRAMFILES\program can't work because of "Program Files" but "C:\program" can.


'"path2exe" params' should work


make sure you encase paths with spaces in quotes?


In my Function un.onInit I've got:

InitPluginsDir
ExecCmd::exec '"$INSTDIR\bin\RtiDeleteUserData.bat"' ""

I'm using ExecCmd instead of just ExecShell because I need it to wait, and I'm using ExecCmd instead of ExecWait because I don't want to see a console window. It worked great for INSTDIR=C:\Program Files\RTI but not for INSTDIR=C:\Program Files (x86)\RTI. If I use /TEST, the console screen flashes too fast to see what's wrong. It's ever getting to run my .bat file, I know that, because that has a PAUSE in it. I know I have the source, and I could build a debug version etc etc, but: anyone have any quicker suggestions? Thanks!


If it's only used temporary to delete some data, why don't you place the batch file in another 'simple' location, like c:\temp, run it from there and delete the batch file afterwards.


Wow, thanks for the quick reply! It's a fairly complex bat file installed with the product. As I understand it, to copy a file w/i NSIS I have to ReadFile/WriteFile. I figured if I'm going to go to that trouble I might as well re-implement the bat file logic within NSIS. Or am I missing something?


I'm not sure what you mean with "As I understand it, to copy a file w/i NSIS I have to ReadFile/WriteFile".

You can add a batch file to your installer like any file, extract it to a temp folder and run it from there.

File /oname=$TEMP\RtiDeleteUserData.bat RtiDeleteUserData.bat
SetOutPath $TEMP
ExecWait '"$TEMP\RtiDeleteUserData.bat"'
SetOutPath $INSTDIR
But if you want to have everything in your script, it will be at least more readable if you do it with NSIS commands instead of creating the batch file at runtime.

Ah, of course, you're using it in an uninstaller.
Sorry.

But you can use CopyFiles to copy the batch file:

CopyFiles $INSTDIR\bin\RtiDeleteUserData.bat $TEMP\RtiDeleteUserData.bat
SetOutPath $TEMP
ExecWait '"$TEMP\RtiDeleteUserData.bat"'
SetOutPath $INSTDIR

Originally posted by jpderuiter
...But you can use CopyFiles to copy the batch file
Doh! Not sure how I missed that. That might solve some other issues for me, too. Thanks!

EcecCmd - mysqladmin with pipe - doesnt work
Hi all,

I am hoping someone can give some advise on the problem I'm having with the installer I'm writing. I have decided I need to use ExecDos or ExecCmd as I need to perform a console operation without showing a Cmd window.

the command I am actually trying to perfom is this:


[PATH]\mysqladmin.exe --defaults-file=[PATH]\my-small****f --user=root --password=root variables | find "basedir" | find "[EXPECTEDBASEDIR]"


The purpose is to launch mysqladmin and find the basedir from the variables output, and thus checking that it is the expected basedir. IE it is OUR mysql server that is running.

So the expected NSIS code is:


;Assuming ${MYSQL} contains the relative path to the mysql directory

ExecCmd::exec '${MYSQL}\bin\mysqladmin.exe --defaults-file=${MYSQL}\bin\my-small****f --user=root --pass=root variables | find "basedir" | find "[EXPECTEDBASEDIR]"'


This works fine when the mysqlserver is up (returns 0 to stack if ffound, 1 otherwise. And also returns 1 as expected if the mysqlserver is not running.

However if the ****f file is configured to listen to a port number that is already in a listening state (for example 80 or any port Apache is running on), mysqladmin hangs for a long period of time.

No problem, thats why we have the /TIMEOUT switch! so the new code is this:

;Assuming ${MYSQL} contains the relative path to the mysql directory

ExecCmd::exec /TIMEPOUT=10000 '${MYSQL}\bin\mysqladmin.exe --defaults-file=${MYSQL}\bin\my-small****f --user=root --pass=root variables | find "basedir" | find "[EXPECTEDBASEDIR]"'


And sure enought the timeout works and pops a nice -8 return value. however there is a problem. After performing the above command and returning from the exec call, the processes (mysqladmin.exe, and 2 instances of find.exe) continue to run and not cease like expected with ExecCmd...

With testing, if I run the cmd with just mysqladmin (removing the 2 calls to find and the 2 pipes) then ExecCmd kills mysqladmin.exe correctly, but not when the output is piped to another app (in this case find)

can anyone help solve this issue?

I cant just leave mysqladmin to timeout and die on its own as the situation can arise where the installer completes but there are still child processes running, which may need to be re-used, and which is against our coding guidelines and is very poor practice.

I do hope someone can help!

Many thanks in advance,

Danny

seems the forum has changed my configuration file extension ([dot]cnf) to ****f, sorry about that!


ExecCmd::Exec changes stack
While struggeling with the probelm described in thread "Execute diskpart", I came to notice, nsExec::exec changes my stack if it failes (return code 1).
Before I'm calling the function, I push a string onto the stack. After calling the function and popping its return code, the value I'm popping from stack has been changed to 0.

I've tried around and figured out, the ExecCmd::exec seems to mix up the stack:

Let's assume, before calling the function, my stack looks like:
A
B
C

- Now, I'm calling the ExecCmd::exec and getting as return: 1.
- My next pop brings me "B" and the next pop "C".

It seems to me, that ExecCmd::exec absorbs my "A".


So far my problem description. I hope someone can understand my gibberish.


Ok, I've tested at a point where ExexCmd::exec ends successfully. It also absorbs the first value on stack.

Summary: ExecCmd::exec pops the first entry from stack.

It would be great, if someone could fix that.


ExecCmd::exec requires at least 2 parameters. Use "" for empty stdin string.