Sign in to follow this  
Followers 0
wibs

Waiting for a window to close before continuing

29 posts in this topic

Hi,

I created a little script to close a cmd window by sending it the 'shutdown' command it requires, like so:

AutoItSetOption ( "WinTitleMatchMode", 2)

WinActivate ( "RegionServer", "")

Send ("shutdown{Enter}")

WinWaitClose("RegionServer")

MsgBox (0,"Confirmation", "The RegionServer has closed down successfully")

This script works fine. The cmd window (RegionServer) got the focus, got the 'shutdown' command, and after about a minute of saving its data it finally closed, and I got the messagebox confirmation.

However, I need to close down 6 of these servers, so I wrote the following script, based on the above first try:

AutoItSetOption ( "WinTitleMatchMode", 2)

WinActivate ( "RegionServer", "")

Send ("shutdown{Enter}")

WinWaitClose("RegionServer")

WinActivate ( "MessagingServer", "")

Send ("shutdown{Enter}")

WinWaitClose("MessagingServer")

WinActivate ( "InventoryServer", "")

Send ("shutdown{Enter}")

WinWaitClose("InventoryServer")

WinActivate ( "AssetServer", "")

Send ("shutdown{Enter}")

WinWaitClose("AssetServer")

WinActivate ( "GridServer", "")

Send ("shutdown{Enter}")

WinWaitClose("GridServer")

WinActivate ( "UserServer", "")

Send ("shutdown{Enter}")

WinWaitClose("UserServer")

The problem is, when I ran this script, all cmd windows closed down at the same time, instead of in the the above sequence, as I expected (they have to be closed down in the correct order). So why didn't each server shutdown not wait until the previous server shutdown had completed?

TIA for any guidance,

Wibs

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Don't know if this would make a difference, but you can make each windowclose its own function and call each function in the main loop...

So

i=0
while i = 0
_close1()
_close2()
...

i=1 (you can maybe add an "if else" check here too)
WEnd


func _close1()
WinActivate ( "RegionServer", "")
Send ("shutdown{Enter}")
WinWaitClose("RegionServer")
Endfunc
Edited by Flam

Share this post


Link to post
Share on other sites

WinActivate ( "RegionServer", "")
Send ("shutdown{Enter}")
While WinWaitClose("RegionServer") = 0
    Sleep(100)
Wend

Try this in all 6 windows.


[center]It's a question of mind over matter, if I don't mind, it doesn't matter.[/center]

Share this post


Link to post
Share on other sites

... all cmd windows closed down at the same time, ...

Welcome to the forum.

What operating system did you run this script of your on?

Are you sure that the cmd windows did not close in the correct order?

You probably should add this line to each section:

AutoItSetOption("WinTitleMatchMode", 2)

WinActivate("RegionServer", "")

WinWaitActive("RegionServer", "")

Send("shutdown{Enter}")

WinWaitClose("RegionServer")

If the Z order of the cmd windows does not happen to be in the order of the script, then the script could be sending the shutdown & Enter to the wrong cmd window... but that should have only caused the script to hangup on a WinWaitClose line.

Grasping at straws here > Does the cmd window happen to change title during shutdown? Using the Window's handle should avoid that issue. See the bottom of this doc page http://www.autoitscript.com/autoit3/docs/i...owsadvanced.htm


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Welcome to the forum.

What operating system did you run this script of your on?

Are you sure that the cmd windows did not close in the correct order?

You probably should add this line to each section:

AutoItSetOption("WinTitleMatchMode", 2)

WinActivate("RegionServer", "")

WinWaitActive("RegionServer", "")

Send("shutdown{Enter}")

WinWaitClose("RegionServer")

If the Z order of the cmd windows does not happen to be in the order of the script, then the script could be sending the shutdown & Enter to the wrong cmd window... but that should have only caused the script to hangup on a WinWaitClose line.

Grasping at straws here > Does the cmd window happen to change title during shutdown? Using the Window's handle should avoid that issue. See the bottom of this doc page http://www.autoitscript.com/autoit3/docs/i...owsadvanced.htm

The script was run on a Windows 2003 Server box.

Yes, I am certain that the windows did not close in the correct order. The first window, the RegionServer, interrogates the 5 other servers to load data, close the connections, saves the data to a MySQL database and other housekeeping duties. It takes around 1 minute on my setup (but this can vary depending on the amount of data, hence the need to wait for it to close before closing the servers in the correct order).

I did not notice if the window title changed, but I will pay attention when I get home from work and give it another go.

When I run the script the RegionServer starts to close, but then I see all the other server windows open and immediately close, resulting in the RegionServer reporting numerous connection errors.

What I don't understand is why the first test script works faultlessly, the MsgBox waits until the RegionServer has closed (after 1 minute) before opening and giving me the confirmation message, so I just don't understand why the subsequent server shutdown commands do not wait likewise.

The only info I neglected to mention, but I do not know if it is relevant, is the the first server window, RegionServer, is maximised on the screen, while the other 5 server cmd windows are all minimised.

I will try your WinWaitActive suggestion and report back.

Thanks for help

Wibs

Edited by wibs

Share this post


Link to post
Share on other sites

Many thanks for the WinWaitActive suggestion. That stopped all the cmd server windows closing at once.

The problem I now have, is that the script will only close windows that are maximised to start with. If only the first one is maximised, and the others minimised to the taskbar (which is normally the case, I have only the RegionServer maximised, and the other 5 child servers minimised to the taskbar), then when it is the turn of one of those minimised windows, it maximises, shows the 'shutdown' command at the cursor, but it appears that the {Enter} key does not get implemented, as it pauses and waits, and I have to press the Enter key manually. This is not the case if I maximise all windows to start off with, in that case they all close in exactly the way I want.

Any ideas on why this is happening?

Current script below:

AutoItSetOption ( "WinTitleMatchMode", 2)

WinActivate ( "RegionServer", "")

WinWaitActive("RegionServer", "")

Send ("shutdown{Enter}")

WinWaitClose("RegionServer")

WinActivate ( "MessagingServer", "")

WinWaitActive("MessagingServer", "")

Send ("shutdown{Enter}")

WinWaitClose("MessagingServer")

WinActivate ( "InventoryServer", "")

WinWaitActive("InventoryServer", "")

Send ("shutdown{Enter}")

WinWaitClose("InventoryServer")

WinActivate ( "AssetServer", "")

WinWaitActive("AssetServer", "")

Send ("shutdown{Enter}")

WinWaitClose("AssetServer")

WinActivate ( "GridServer", "")

WinWaitActive("GridServer", "")

Send ("shutdown{Enter}")

WinWaitClose("GridServer")

WinActivate ( "UserServer", "")

WinWaitActive("UserServer", "")

Send ("shutdown{Enter}")

WinWaitClose("UserServer")

Many thanks for the help so far,

Wibs

Share this post


Link to post
Share on other sites

@wibs

Instead of WinWaitClose use :

While WinExists("RegionServer")
Sleep(10)
WEnd
Msgbox(64,"RegionServer","Window closed !")

Cheers, FireFox.


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

@wibs

Instead of WinWaitClose use :

While WinExists("RegionServer")
Sleep(10)
WEnd
Msgbox(64,"RegionServer","Window closed !")

Cheers, FireFox.

Hi guys,

I tried all the suggestions, but nothing works. Some suggestions nearly work, but it just seems that the commands do not do what their description says they should do.

I have found that putting a Sleep(500) line before the WinWaitClose almost does it. It closes each window, one-by-one, and after the previous one has closed, except the last window, which is just there, with the shutdown command inserted, but as if the last {Enter} had not been sent.

I don't feel I am learning very much. There are plenty of suggestions, but no reasoning given. Why doesn't WinWaitClose work as it is described in the help file?

Why does this script work:

Run("cmd.exe", "C:\WINDOWS\system32", @SW_MAXIMIZE)

Sleep(100) ;in milliseconds

WinSetTitle("C:\WINDOWS\system32\cmd.exe", "", "RegionServer")

But this one doen't?

Run("cmd.exe", "C:\WINDOWS\system32", @SW_MAXIMIZE)

WinSetTitle("C:\WINDOWS\system32\cmd.exe", "", "RegionServer")

I am not finding this scripting very intuitive at all :)

Wibs

Share this post


Link to post
Share on other sites

Any last suggestions on this problem, before I look at alternative scripting/languages to accomplish this task?

I really thought when I looked at the AutoIt command/function list that it had everything in there I needed to accomplish this simple (well it seems simple) task, i.e to close 6 cmd windows, in a particular order, whether or not the windows are maximised or minimised to the taskbar.

Wibs

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

...

Run("cmd.exe", "C:\WINDOWS\system32", @SW_MAXIMIZE)

WinSetTitle("C:\WINDOWS\system32\cmd.exe", "", "RegionServer")

...

The time between these two lines of code is too small.

The window was not present for the WinSetTitle command to act on.

Your code has no error checking...

...it does not check to see if WinSetTitle returned a 1.

You can use sleep statements - but that is very hit and miss and not what sleep statements are good for. A simple WinWait would help.

CMD windows are - ummm - different from normal OS GUIs. You did not pick the simplest task to automate, but AutoIt should be able to do what you need.

You can do this Send ("shutdown{Enter}") but you might want to consider doing:

Send("shutdown")

Sleep(500)

Send("{Enter}")

Also, when/if you are ready to dive in deeper - AutoIt has STDIO functions that may be able to communicate directly to the CMD windows of interest.

Edited by herewasplato

[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

The time between these two lines of code is too small.

The window was not present for the WinSetTitle command to act on.

Your code has no error checking...

...it does not check to see if WinSetTitle returned a 1.

You can use sleep statements - but that is very hit and miss and not what sleep statements are good for. A simple WinWait would help.

CMD windows are - ummm - different from normal OS GUIs. You did not pick the simplest task to automate, but AutoIt should be able to do what you need.

You can do this Send ("shutdown{Enter}") but you might want to consider doing:

Send("shutdown")

Sleep(500)

Send("{Enter}")

Also, when/if you are ready to dive in deeper - AutoIt has STDIO functions that may be able to communicate directly to the CMD windows of interest.

Many thanks for that. I was starting to feel that the basic problems I was having related to timing issues.

Your suggestions of putting a sleep() between the two Send()s, and between the Run and WinSetTitle could indeed solve those problems, however the Help that comes with AutoIt gives no such examples, nor any warning about timing, and I guess a lot of newbies like myself start out by copy/pasting the command/function examples from the Help file.

I was also under the impression (or misapprehension) that commands in a simple script (with no loops or branches) executed sequentially, and no command started until the previous command had completed. That appears not to be the case with AutoIt, and I guess some words in the Help file would alleviate many calls for help in the forum. The samples in Help would also be better served with clearer examples of how to wait until until a command has completed (if sequential execution is a requirement).

It does seem a bit wasteful to have While/Wend or If loops around every command, or a profusion of Sleep() statements, just to force the script to only execute a command after the previous one had completed. A 'Sequential' parameter at the beginning of a script would be a much better way, and reduce code significantly, would it not?

Again, many thanks for the suggestions,

Wibs

Share this post


Link to post
Share on other sites

... however the Help that comes with AutoIt gives no such examples, nor any warning about timing, and I guess a lot of newbies like myself start out by copy/pasting the command/function examples from the Help file. ...

Working thru the "notepad tutorial" in the help file would have pointed out

Run

WinWait

Send

... It does seem a bit wasteful to have While/Wend or If loops around every command, or a profusion of Sleep() statements, just to force the script to only execute a command after the previous one had completed. ...

No loops are needed for your script. Properly written, things will run sequentially. The loop that FireFox posted in this thread is a faster version of the single line WinWaitClose. You will never notice the ~200ms that the loop trims.

WinActivate("RegionServer", "")

WinWaitActive("RegionServer", "")

Send("shutdown")

Sleep(500)

Send("{Enter}")

WinWaitClose("RegionServer")

...just repeat that for each CMD of interest and post back.

Most apps can buffer what you send them (up to a point); the CMD window can too, but it is weird about some things.

Are you still having a problem with the min/max window issue or was it just a case of the window of interest not being ready for more input after sending the shutdown characters?


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

If you encounter problems using Send() then try to use ControlSend() or ControlSetText() instead.

In your case: ControlSend()

Look at Au3Info tool to get right ClassNameNN

EDIT:

Source of problems with Send() may be in stolen focus (after some text is typed) by another application.

You may also take a look at SendKeepActive()

Workaround for this is ControlSend()

Also look at AutoItSetOption - SendKeyDelay I think when you set higher value your original script maybe it will work fine even without inserted Sleep()

Edited by Zedna

Share this post


Link to post
Share on other sites

Thanks for the patience herewasplato:

Here is the modified script, but alas, still does not work:-

Dim $RS = "RegionServer"
Dim $MS = "MessagingServer"
Dim $IS = "InventoryServer"
Dim $AS = "AssetServer"
Dim $GS = "GridServer"
Dim $US = "UserServer"

AutoItSetOption ( "WinTitleMatchMode", 2)

WinActivate ($RS, "")
WinWaitActive($RS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($RS)

WinActivate ($MS, "")
WinWaitActive($MS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($MS)

WinActivate ($IS, "")
WinWaitActive($IS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($IS)

WinActivate ($AS, "")
WinWaitActive($AS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")

WinWaitClose($AS)

WinActivate ($GS, "")
WinWaitActive($GS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($GS)

WinActivate ($US, "")
WinWaitActive($US, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($US)
MsgBox(0,"Shutdown Completed", "OpenSim has now shutdown...", 3000)

Again, the script works only on the first (maximised) cmd window, but each of the other minimised cmd windows this is what happens:

window maximises

the word 'shutdown' appears

the window does not then go through the shutdown process as it appears to still be waiting for the {enter} keystroke

If I manually press the <Enter> key, it performs the shutdown, then the same situation with the next window, and so on, till I get the MsgBox.

However, if I maximise all windows and have them all over my desktop, then the script works fine from start to finish. It is definitely the minimised windows that are still giving trouble, so i guess that answers your last question.

Any ideas? How about a WinSetState @SW_Maximize first?

Wibs

Share this post


Link to post
Share on other sites

If you encounter problems using Send() then try to use ControlSend() or ControlSetText() instead.

In your case: ControlSend()

Look at Au3Info tool to get right ClassNameNN

EDIT:

Source of problems with Send() may be in stolen focus (after some text is typed) by another application.

You may also take a look at SendKeepActive()

Workaround for this is ControlSend()

Also look at AutoItSetOption - SendKeyDelay I think when you set higher value your original script maybe it will work fine even without inserted Sleep()

Thanks for that Zedna. I can see how stolen focus could cause problems, thanks for the alternative suggestions, I will look into them. For now, that does not apply to my setup, as nothing else else is going on except for trying to close down the servers that make up this virtual world, but if I distribute this solution to others who want a one-click solution to shutting down OpenSim, then i must take into account the fact they they might have other things going on on their servers, quite different to mine. So I will definitely look into it after getting the initial problems sorted out. I will also experiment with the AutoItSetOption.

Thanks again

Wibs

Share this post


Link to post
Share on other sites

... How about a WinSetState @SW_Maximize first? ...

Sounds good, but I still don't see why you should have to do that.

I know, buy me a license for w2003 server and I'll test your code :-) :-) :-) :-)

I'm not sure that you should be thanking me just yet. It has been a long time since I've scripted the CMD window without using STDIO. I might have forgotten what works and what doesn't - I might be sending you down the wrong rabbit trail. That is why I PM'd Zenda and asked for a second set of eyes.

I gotta run for a while - will check back in on your progress later.

~Most Senile Poster~


[size="1"][font="Arial"].[u].[/u][/font][/size]

Share this post


Link to post
Share on other sites

Hahahah. I don't know whether to laugh, or cry!

I tried replacing all my WinActivate functions with WinSetState, i.e.

WinSetState ($RS, "", @SW_SHOWMAXIMIZED)
WinWaitActive($RS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($RS)

WinSetState ($MS, "", @SW_SHOWMAXIMIZED)
WinWaitActive($MS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($MS)

The WinSetState flag @SW_SHOWMAXIMIZED is suppossed to activate a window AND maximize it. Just what I needed. However....

The window activated and maximized alright, but instead of 'shutdown' then appearing in the window, I got 'sshhuuttddoowwnn' !!!!!

Is there a WinStutterOff command?

Heheheh,

Wibs

Share this post


Link to post
Share on other sites

Hahahah. I don't know whether to laugh, or cry!

I tried replacing all my WinActivate functions with WinSetState, i.e.

WinSetState ($RS, "", @SW_SHOWMAXIMIZED)
WinWaitActive($RS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($RS)

WinSetState ($MS, "", @SW_SHOWMAXIMIZED)
WinWaitActive($MS, "")
Send ("shutdown")
Sleep(500);in milliseconds
Send("{Enter}")
WinWaitClose($MS)

The WinSetState flag @SW_SHOWMAXIMIZED is suppossed to activate a window AND maximize it. Just what I needed. However....

The window activated and maximized alright, but instead of 'shutdown' then appearing in the window, I got 'sshhuuttddoowwnn' !!!!!

Is there a WinStutterOff command?

Heheheh,

Wibs

Try

ControlSetText ($MS, "", "ClassNameNN", "shutdown")

instead of

Send ("shutdown")

Of course don't forget to replace ClassNameNN by real value!

I'm not sure if it will work in case of CMD window. I used this workaround successfully in some of my projects

where I had problems with Send() and Czech national keyboard layout.

Share this post


Link to post
Share on other sites

Try

ControlSetText ($MS, "", "ClassNameNN", "shutdown")

instead of

Send ("shutdown")

Of course don't forget to replace ClassNameNN by real value!

I'm not sure if it will work in case of CMD window. I used this workaround successfully in some of my projects

where I had problems with Send() and Czech national keyboard layout.

Thanks for that Zedna, but using Au3Info.exe and hovering the cursor over the RegionServer window gives me the Title and Class, but produces no value for ClassNameNN. If I move the cursor off that window and onto the Desktop then I get Program Manager for the Title, and all the lower data, including ClassNameNN, gets populated (just as a check that Au3Info.exe was doing its stuff).

I will try the other two suggestions (the one from Firefox and the one from you in your last post) tomorrow.

Damn odd that 'sshhuuttddoowwnn'. Any idea what could cause that?

Wibs

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0