Sign in to follow this  
Followers 0
Bert

When one program closes another program

13 posts in this topic

I have 2 scripts.

Script "A" is my toolbar script I use everyday in the office. Works fine

Script "B" is a report generator that now and again gets stuck due to the website it pulls the report from getting stuck. No biggy, for I usually just run the report again.

What I'm trying to do is have Script "A" stop script "B". Script "B" may have a IE window open when it is forces closed by Script "A"

My question is this: When Script "B" is forced closed, is it possible to have it do a couple of things while it is being closed? I want it to clean up behind itself if forced closed. Is this possible?

A second route woud be just getting it to restart without closing, but I like not have to do a big rewrite of the code to make this happen.

Thoughts?

Share this post


Link to post
Share on other sites



I have made some scripts with a timer to check every 30 seconds (or after a certain amount of time) and ask for user input in case the script was hung for some reason. You could have it bypass user input so it wouldn't need script A to do this.

However, since you want script A to be able to stop script B... You need script B to be able to either check for some type of flag (file created, system or shared string changed, etc.) from script A indicating what you want it to do.

The best/coolest option would be for script A to talk directly to script B. I don't know right off how to do that unless the shared string between the scripts is possible. You could have script B just check the shared string at preset intervals or on certain events.

AutoIt has the AdlibEnable function and (I think) one or two others that allow for automatic/timed running of functions.


Be open minded but not gullible.A hammer sees everything as a nail ... so don't be A tool ... be many tools.

Share this post


Link to post
Share on other sites

This requires ProcessB to have a window handle. I think AutoIt gives a default window handle to every process but i'm not sure how you find it.

ProcessA:

#include <misc.au3>

$hWnd = WinGetHandle ( "ProcessB")

_SendMessage($hWnd, $WM_CLOSE)oÝ÷ Øúèqë,«­¢+Ø¥¹±Õ±ÐíU%
½¹ÍѹÑ̹ÔÌÐì(í
½¹ÍÐÀÌØí]5}
1=MôÁàÀÀÄÀ()U%
ÉÑ ÅÕ½ÐíAɽÍÍÅÕ½Ðì¤ìÝ¥±°ÉÑ¥±½½àÑ¡ÐÝ¡¸¥ÍÁ±å¥Ì¹ÑÉ)U%MÑMÑÑ¡M]}M!=¤ìÝ¥±°¥ÍÁ±ä¸µÁÑ䥱½½à()U%I¥ÍÑÉ5Í ÀÌØí]5}
1=M°ÅÕ½ÐíI¥ÙÅÕ½Ðì¤((ìIոѡU$չѥ°Ñ¡¥±½¥Ì±½Í)]¡¥±Ä(ÀÌØíµÍôU%Ñ5Í ¤((%ÀÌØíµÍôÀÌØíU%}Y9Q}
1=MQ¡¸á¥Ñ1½½À)]¹()Õ¹I¥Ù ¤(5Í ½à À°ÅÕ½ÐìÅÕ½Ðì°ÅÕ½ÐíQMPÅÕ½Ðì¤(á¥Ð)¹Õ¹

Share this post


Link to post
Share on other sites

use OnAutoitExit function in script B to run any cleanup code before exiting

and use WinClose in script A to Close B, even if your script B has no GUI elements

you can WinClose by the hidden window name 'AutoIt v3' that you could rename in script B

to something unique


I see fascists...

Share this post


Link to post
Share on other sites

use OnAutoitExit function in script B to run any cleanup code before exiting

and use WinClose in script A to Close B, even if your script B has no GUI elements

you can WinClose by the hidden window name 'AutoIt v3' that you could rename in script B

to something unique

This might work too. You can use:

AutoItWinSetTitle ("ProcessB")

This will avoid closing other AutoIt programs you may have running.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

yes weaponx I was about to post an example with that but I used a MsgBox in the While loop

as a blocking function to simulate a process waiting for a return as Volly is having with waiting for a website.

(some timeout error handling would be good for that script)

Edit: I didn't add that smiley intentionally, an accidental 'B' before the closing parentheses created an unintended smiley..

and was instantly reminded that a blocking function prevents WinClose,

I think MsCreator had a thread on that subject a while back.

Edited by rover

I see fascists...

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Here is rovers method:

ProcessA:

(WinGetHandle probably isn't necessary here but oh well)

WinClose(WinGetHandle("ProcessB"))oÝ÷ Ù³ë¡Ç¬°Ûjëh×6#include <GUIConstants.au3>

Opt("OnExitFunc","Cleanup")

GUICreate("ProcessB")
GUISetState (@SW_HIDE)

; Run the GUI until the dialog is closed
While 1
    $msg = GUIGetMsg()
    
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
Wend
    
Func Cleanup()
    MsgBox(0,"","Performing cleanup")
    Exit
EndFunc

I also tried using GUICtrlCreateDummy but I could not get the dummy control in ProcessB to receive commands from ProcessA...

EDIT: Don't forget, neither of these methods will provide protection against the task being killed with ProcessClose() or through the Task Manager

Edited by weaponx

Share this post


Link to post
Share on other sites

an attempt to do it all in Script "B"

if script B run second time it will close first instance of Script B

first politely with WinClose, then if script is unresponsive terminated with extreme prejudice with ProcessClose

option to do cleanup on normal WinClose exit and at start of second instance to do post script processclose cleanup

comments?, critiques?

; Script B or Process B
#include <Misc.au3>
Func OnAutoItStart()
    ; if instance of script with "Script B" title is running its closed by second instance
    If Not _Singleton("scriptb",1) Then; Mutex is now: "scriptb"
        WinClose("Script B","") ; try closing first instance of script politely
        WinWaitClose("Script B","",5) ; timeout value to accomodate script cleanup at shutdown

        ; if WinClose not succesful then processclose and perform cleanup first instance would have done
        If WinExists("Script B","") Then ; WinKill("Script B","")
            $list = ProcessList("script-autoclose.exe"); use brute force if first instance not responding
            For $i = 1 to $list[0][0]
              If $list[$i][1] <> @AutoItPID Then ProcessClose($list[$i][1])
            Next
            If Not WinExists("Script B","") Then
                ; any cleanup code not performed by normal script exit
            Else
                Exit (2) ; exit, hung script not closed
            EndIf
        EndIf
    EndIf
    
    AutoItWinSetTitle("Script B") ; if script B has no GUI..
    ; Title of hidden script window changed from default 'AutoIt v3' to "Script B"
EndFunc


While 1
    Sleep(1000)
    MsgBox(0,"","") ; will cause second instance of script to use processclose after winclose fails
    ; blocking function, should simulate unresponsive script hang due to waiting for website
WEnd

Func OnAutoItExit()
    If @exitCode <> 2 Then ; _Singleton() exit, bypass any script shutdown cleanup
        ; cleanup code on script closure
        Beep(1000,5) ; normal script shutdown (Optional)
    EndIf
EndFunc

I see fascists...

Share this post


Link to post
Share on other sites

@rover I think you lost sight of what Volly wanted. He already hasd an external app (Script A) that has to fire off the exit command to Script B. I don't think he was worried about multiple instances of Script B running, thats a whole other story.

Share this post


Link to post
Share on other sites

I came up with a solution that works. I did test OnExitFunc, and found it didn't work for me. What I ended up doing was in Script "A", I had it do a check afterit killed "B". Script A" is performing the cleanup. Seems to work fine. Thanks for the help. My solution looks like this:

func _restart()
    if ProcessExists("sr.exe") then 
        ProcessClose("sr.exe")
        $IEwin = IniRead($pth, "IEwindowlocation", "1","")
        if WinExists($IEwin) then WinKill($IEwin);first check via handle
        $var = WinList()
        For $i = 1 to $var[0][0];second check via windowpos. 
            $g = WinGetPos("")
            If $var[$i][0] <> "" and $g[0] = -5000 and $g[1] = -5000 Then
                $I1 = IniRead($pth, "IEwindowlocation", "2","")
                $I2 = IniRead($pth, "IEwindowlocation", "3","")
                WinMove($var[$i][0],"",$I1, $I2)
                WinKill($var[$i][0])
            endif
        next    
        sleep(1000)
        run(@ScriptDir&"/sr.exe")
    Else
        $qst = MsgBox(36, "SRCR is not running!", "Did you want to run a report?", 10)
        if $qst = 6 then run(@ScriptDir&"/sr.exe")
        if $qst = 7 then sleep(0)
    endif       
EndFunc

Share this post


Link to post
Share on other sites

that script isn't about multiple instances

Script A runs Script B a second time to close first unresponsive Script B and replace it with a new instance

_Singleton() has more than one use

in this case its used to detect the existance of an instance of itself already running

and try to close that instance politely with WinClose (this will fail if that script is waiting for an event,

like a blocking function, i.e. Msgbox or wait for SendMessage return)

in other words the app is hung and unresponsive to WinClose

so processclose is used

either way the second instance of the script forces a normal shutdown and cleanup via the first instances OnAutoitExit() function

or it performs the cleanup itself after terminating the first instance

if the script is run a second time it closes any existing instance

i.e.

script b is stuck waiting for the website

volly clicks on toolbar Script A to run Script B a second time

the second instance of script B kills the first script B that is hung up

not itself as _Singleton() is normally used for.

volly wants to have Script B cleanup after itself on close

that will work only if the script is not hung (blocking function, etc.)

when OnAutoitExit() functions runs on normal exit

but if the script can only be closed with Processclose then the cleanup

either has to be done by script A or by a new instance of Script B

maybe whats needed is AdlibEnable or the Timers UDF or any other asynchronous process

thats not rendered unresponsive by a blocking function in script B

I think Script B should have code to handle the unresponsive website issue itself.


I see fascists...

Share this post


Link to post
Share on other sites

A couple of months ago I posted a UDF _ChildProcess to RAVE reviews :) ...

Well, anyway, you might find it useful for finding and stopping any process running that are children of the process you're checking.

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