safely closing another application that is running programmatically

Posted on 2005-05-04
Last Modified: 2012-06-27
I've two executables and i want exe1 to be able to close exe2.

I konw that if i made them ActiveX EXEs then i could use COM to just call a method in teh 2nd exe that would get it to exit - but i don't want them to be ActiveX EXEs.

Is there a way to safely close another program from code?

i.e. - i still want all the events to fire in exe2 that normally fire when a program exits when the user clicks the "x" - i don't just want to terminate the process (because its always working with an access db and i'm afraid that if exe1 just terminates the exe2's process - then that will cause database corruption).

is there a win32 api call i can use to cause exe2 to exit naturally?
Question by:kenshaw
    LVL 35

    Expert Comment

    by:[ fanpages ]
    Why not change your exe1 to write a record to a pre-defined table in the database, and have the exe2 monitor this same table for the existence of a record.

    Once the record is read by exe2, it is deleted, and exe2 closes normally.



    LVL 4

    Author Comment

    yeah i could do that... its just not very elegant - its not event based at all.

    I wolud rather the code be clear that the second executable is exiting directly in response to an event in the first exe
    LVL 35

    Expert Comment

    by:[ fanpages ]
    The SendMessage API should do want you need, as long as you know the window handle of the exe you wish to close.

    Is the .exe filename know to you, or does the Window always have the same caption?
    LVL 35

    Expert Comment

    by:[ fanpages ]
    LVL 35

    Accepted Solution

    Another approach:

    This set of functions determines if a window is open and if necessary closes that window. This is useful to avoid opening multiple instances of an application, especially if the application is a hidden background operation. To achieve this function, 5 windows API calls are employed to determine all open applications, check their identity and message these applications in order to issue a closedown call if required. The code below can be copied to a module and forms a complete working unit:
       Option Explicit
       Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
         (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
       Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
         (ByVal hwnd As Long, ByVal lpString As String, _
         ByVal aint As Long) As Long
       Declare Function GetWindow Lib "user32" _
         (ByVal hwnd As Long, ByVal wCmd As Long) As Long
       Declare Function EnumWindows Lib "user32" _
         (ByVal wndenmprc As Long, ByVal lParam As Long) As Long
       Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
         (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
         lParam As Any) As Long

       Private Const WM_CLOSE = &H10
       Private Const GW_HWNDFIRST = 0
       Private Const GW_HWNDLAST = 1
       Private Const GW_HWNDNEXT = 2
       Private Const GW_HWNDPREV = 3
       Private Const GW_OWNER = 4
       Private Const GW_CHILD = 5
       Private Const GW_MAX = 5

       Private mstrTarget As String
       Private mblnSuccess As Boolean

    Public Function blnFindWindow(strApplicationTitle As String) As Boolean

       Dim hWndTmp As Long
       Dim nRet As Integer
       Dim TitleTmp As String
       Dim TitlePart As String
       Dim MyWholeTitle As String
       Dim mCounter As Long
       Dim hWndOver As Integer
       Dim sClassName As String * 100

       blnFindWindow = False

       TitlePart = UCase$(strApplicationTitle)

       'loop through all the open windows
       hWndTmp = FindWindow(0&, 0&)

       Do Until hWndTmp = 0

          TitleTmp = Space$(256)
          nRet = GetWindowText(hWndTmp, TitleTmp, Len(TitleTmp))

          If nRet Then
             'retrieve window title
             TitleTmp = UCase$(VBA.Left$(TitleTmp, nRet))
             'compare window title & strApplicationTitle
             If InStr(TitleTmp, TitlePart) Then
                blnFindWindow = True
                Exit Do
             End If
          End If

          hWndTmp = GetWindow(hWndTmp, GW_HWNDNEXT)
          mCounter = mCounter + 1


       End Function

    Public Function blnCloseWindow(strApplicationTitle As String) As Boolean

       ' retrieve Windows list of tasks.
       mblnSuccess = False
       mstrTarget = strApplicationTitle
       EnumWindows AddressOf EnumCallback, 0
       blnCloseWindow = mblnSuccess

    End Function

    Public Function EnumCallback(ByVal app_hWnd As Long, _
      ByVal param As Long) As Long

       Dim buf As String * 256
       Dim title As String
       Dim length As Long

       ' Checks a returned task to determine if App should be closed

       ' get window's title.
       length = GetWindowText(app_hWnd, buf, Len(buf))
       title = Left$(buf, length)

       ' determine if target window.
       If InStr(UCase(title), UCase(mstrTarget)) <> 0 Then
          ' Kill window.
          SendMessage app_hWnd, WM_CLOSE, 0, 0
          mblnSuccess = True
       End If

       ' continue searching.
       EnumCallback = 1

    End Function
    The usage of these function is straight forward and fall into 2 parts: determining if a specific application is open and if necessary closing that application. The 2 function all are as follows:

       If blnFindWindow("Notepad") Then
           If Not blnCloseWindow("Notepad") Then
               MsgBox "Problems encountered closing Window", _
                 vbInformation, "API Call"
               Exit Sub
           End If
       End If


    LVL 4

    Author Comment

    i know the exe filename - and only one of the file can run at any time
    LVL 4

    Author Comment

    actually - that last bit is wrong - i'm actually closing two exes (i.e. exe2 and exe3) and exe3 is an activeX  EXE with singleuse classes in it - so there could be multiple processes running of that executable - all with the same name... i want to get all of them to exit though
    LVL 35

    Expert Comment

    by:[ fanpages ]
    Try the link I posted above, [ ], for help with closing all executables that share the same filename.
    LVL 23

    Expert Comment

    Take a look at this PAQ :

    It basically is to do with finding any running processes with the exe name and you would need to modify the code however I am sure you could alter the code in this PAQ to suit your needs :)

    Featured Post

    How to run any project with ease

    Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
    - Combine task lists, docs, spreadsheets, and chat in one
    - View and edit from mobile/offline
    - Cut down on emails

    Join & Write a Comment

    Suggested Solutions

    I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
    Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
    As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
    Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

    746 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now