Archive: Quit NSIS when an app is fully initialized


Quit NSIS when an app is fully initialized
Is it possible for NSIS to monitor task manager or the like to monitor the initialization of an app launched by execshell ?
;
Currently, I am guessing when the app will fully load. This time varies between computers. In my case the app is fully loaded/initialized when it starts downloading movies. Be nice to have NSIS quit/hide when the app gets to this state. Is this possible ?

g


Check out the process plug-in at http://nsis.sourceforge.net/wiki/Processes_plug-in


thanks :)
I'll check it out. The only problem I forsee is that the task shows up before anything really happens that is CPU intensive.
Some computers will initialize the app in 3 seconds...others will be about 10 seconds
g


What exactly does the said app do? If it displays a window, you could setup a loop to see when the window appears (such as FindWindow, sleep, loop, FindWindow, etc.). Of course, you'd want to add a counter so that if it looped x number of times without seeing the window, it would exit. (Otherwise, you'd get an infinite loop if the app for some reason never displayed the window.)

And here's something else:
I used to write my own VBScripts using Internet Explorer for an output window. (They were mainly just for small batch files I used on my own.) I learned in doing so that IE has a "ReadyState" property that you can read to determine if it's ready to display a page.

It may just be something for IE, but just in case it helps, here's the link about it.
http://msdn.microsoft.com/workshop/b...state_enum.asp


What exactly does the said app do?

If it displays a window, you could setup a loop to see when the window appears (such as FindWindow, sleep, loop, FindWindow, etc.). Of course, you'd want to add a counter so that if it looped x number of times without seeing the window, it would exit. (Otherwise, you'd get an infinite loop if the app for some reason never displayed the window.)

Otherwise, you'd probably have to have a plugin of some type that could hook into the other app somehow. (Is this even possible?) Or maybe you could use a SendMessage command to read a certain value from the process. I'm just not sure what, if anything, that might be...


I wonder if I can have my app [a wired Quicktime movie] send a string to 127.0.0.1:8181 or some other port that NSIS can listen for....So, when the app is ready, it sends the string.
;
my wired QT app is similar to a JAVA app

g


I take it you've made the application yourself, then? In that case, one option would be to have your installer use a special command-line parameter to start the application. If this is used, your application will try to find the installer and send a WM_CLOSE message to it.

However, this means the installer won't be shutting down cleanly.

A more useful approach might be to bundle a small executable in your installer to do the booting of this program (again with a special parameter).

Your installer loads this executable with ExecWait, which in turn starts up your application with the aforementioned parameter and idles after that. Your application finds the "bootstrap" and sends a WM_CLOSE message to it. This will close the bootstrap and allow your installer to continue normally.


Yes, I built the app so I have control :)
You can skip this, but here is the context:
;
This is how NSIS works with the 'media player' app.
NSIS acts as helper app for this media player. The user clicks on the NSIS app and then...
NSIS check's for updates, a Quicktime Install, and admin privs. If everything is OK, NSIS takes the info and builds an xml list of user environment variables, and sends that info to a mysql/php server, and then downloads the QT movie/app into the $PluginsDir. The app reads the newly NSIS created xml file and then NSIS quits. If QuickTime needs to be installed, the installer page begins...and QuickTime is silently installed. Once that is done, the media player is launched. Currently, I have NSIS on a timer to quit after hiding for 15 seconds once ExecShell is issued.
;
What I would really like to do is to set up some kind of locahost port that NSIS and this app where can communicate.
The app sends a string to 127.0.0.1:8181 [or the like]
;
As to WM_CLOSE
Unfortunately, I do not think the platform was built with the power to find the bootstrap'd parameter. Kind of sucks cause it would really come in handy for a whole lot of things.
;
At this point it seems that the only way to pull this off to find/design/augment a NSIS plugin that can listen to a local port and process incoming strings...

thanks pidgeot :)
g


How about something like this: NSIS install launches your media player with a command line like (/init=1 or whatever). Then in the media player code the last thing it does during it's initializing is check to see what the command line parameter was. If it was 1 it writes out a text file. Meanwhile, the NSIS install is watching in a loop for that file to exist. Similar to the loop Comperio
mentioned but use IfFileExists. Once it sees the file the install deletes it and then closes itself down.


Thanks Scully :)
This particular app is more similar to a Flash movie on steroids than a 'real' application. For the past year, I have been using NSIS to fill in the gaps. So far, the two have existed pretty harmoniously. This is pushing the envelope a bit.
;
With this 'Quicktime wired' platform, you can not write text files to the user's hard drive or issue command lines. :(
This is too hobbled to be called a real 'app' , but it does other things so well as it operates cross-platform,with a tiny file size, and a custom server generated skin, and etc. It is ideal as a media player and frankly sucks as a normal app.
;
I can send out a debug string with a GET/Post request to a local port. My hope is that I can send out:
;
http://127.0.0.1:8181?message="I'm fully initialized and have read the xml file of user variables NSIS has so conveinently created for me! Quit NSIS."
;
A plugin seems to be the only solution at this point.
;
Seems like it would be useful for all kinds of applications though. Be great to have NSIS hidden in the background and perform some heavy lifting for multimedia apps of this type.
;
I wonder if there is a NSIS plugin that is similar to something like this that can be modified. I am going to start learning NSIS plugin design a bit this week...
;
g


Worst case scenario:
I can have my media player app change a database variable on the server, and have NSIS make db queries every second or so...to see if the variable has been altered...
Seems like a lot of wasteful db querying though...and may be no more accurate than putting NSIS on a timer to quit
g


If you are able to use the port listening, a workaround would be to use a bootstrap that is started with ExecWait from NSIS, and which then starts your application and listens on that port. Your application sends out a message on that port, and when heard by your bootstrap, it closes itself, causing NSIS to continue (meaning quit).

You'd probably want to use ShellExecuteEx from your application, so you can monitor if the application closes just in case your application doesn't get to send the message.


May be I misunderstood something, but:
If you want to use IP message for syncronization only (or you can transfer other info in some other way) the common way is mutex - supported on all platforms I know. Or 2 mutexes :) And (as I wrote earlier) this not require to solve Windows firewall problem for installer listening a port. Not a problem to use mutex from NSIS script - I saw samples preventing 2 installers to be launched.
Another way (how UNIX guys will do this :) ) is to track ifconfig/ipconfig output for your QT app outgoing connection, but this is a bit more complex parsing.


I actually use mutex to prevent NSIS from launching twice. Unfortunately, the multimedia app can not create a mutex on its own, AFAIK. Maybe a mutex can be created for the app by NSIS....
Sounds like parsing ifconfig/ipconfig string would work though :) Did a little research on netstat and it seems promising. Listen to a specific port in verbose mode and parse the string. Can netstat be run in the background within NSIS ? Progress :)
g


Yes, netstat, but -l not works on my XP, so -a only :(
nsExec or ExecDos (with async/background option).
BTW if your app can read xml file what about file creation (another way of interprocess communication)? Installer can check file in the PLUGINSDIR (IfFileExists init.ok or init.failed and Sleep 500 in the loop).


With netstat, I was able to capture communication from my media player app :) The url being sent to port 8181 is : http://127.0.0.1:8181?message=hello

Is netstat capable of capturing the url string too? Then, I could parse the string. Currently, all I can get is the below. Getting a lot closer though :)

netstat -p TCP
Proto Local Address Foreign Address State
TCP virtualpc:1587 virtualpc:8181 SYN_SENT


Originally posted by grahama
Worst case scenario:
I can have my media player app change a database variable on the server, and have NSIS make db queries every second or so...to see if the variable has been altered...
Seems like a lot of wasteful db querying though...and may be no more accurate than putting NSIS on a timer to quit
g
thats it

-----------------------------

monkey

You can use GetExitCodeProcess (via the System plug-in) to determine whether a process is running or not (it will return the 'exit code' of STILL_ACTIVE if the process is still running). If the function returns an error, assume that the app has not complete initialising and wait a while (say 1 second) longer. You will probably need a timeout period like say 60 seconds at which point you should probably assume the run has failed.

For a more detailed example take a look at the ProcessDirectiveFile function in CABSetup.c source code for the CABSetup plug-in. The function launches a child process and then wants to centre the child's window on the screen and therefore needs to wait until the window is there. The particular section of code could be ported to NSIS with the help of the System plug-in.

Another way is to create an synchronisation Event and have the child process signal (Set) it when it has completed initialisation. The parent process can use WaitForSingleObject on this Event to wait for the child. This is also fairly straightforward with the use of the System plug-in; I have already done it for one of my installers to wait for another process to complete initialisation before terminating the original installer.

Duncan