Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I close a running program? 3

Status
Not open for further replies.

EnS

Programmer
Oct 29, 2002
58
US
Hello,
I have a program that, ideally, should not be run concurrently with EXCEL. I have been able to determine whether or not a session of EXCEL is running using the FindWindow function but now I need to know how to close the session programmically. I have been able to get the ThreadId using the GetWindowThreadProcessId and tried terminating the session with TerminateProcess and TerminateThread with no luck. Does anyone have any suggestions?

Thanks

ERM
 
Given you have the app's window handle:
Code:
Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, lpdwProcessId As Long) As Long

Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long

Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long

Const PROCESS_ALL_ACCESS = &H1F0FFF
'_______________________________

Public Sub sKillProcess(Byval hWnd As Long)

  '--- Kills a running application

  '--- Parameter
  '    hWnd: the application's window handle

  Dim lngRtn As Long
  Dim lngProc As Long
  DimlngProcID As Long

  lngRtn = GetWindowThreadProcessId(hWnd, lngProcID)
  lngProc = OpenProcess(PROCESS_ALL_ACCESS, Clng(0), lngProcID)
  lngRtn = TerminateProcess(lngProc, Clng(0))

End Sub

Paul Bent
Northwind IT Systems
 
paulbent,

Thanks a ton! I've been stressin' over this one for a while. Awsome.

ERM
 
I'm new to using APIs.

EnS,

I tried FindWindow("Excel", "Microsoft Excel") and it didn't work. What am I doing wrong? Secondly, how did you get the theadID? I know these are low level questions but this has already been very helpful!

PaulBent,

Thanks for posting some code. That's what I love about these forums, you can learn a lot just by browsing answers to other's post.


Have a great day!

j2consulting@yahoo.com
 
SBendBuckeye,

The FindWindow API call returns the windows handle. It works by searching for the applications class name and/or the window name. Try the following to retrieve an EXCEL window handle:

Declare the API function:
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As Long) As Long

Call the API function:
'Constant declaring EXCEL class name
Const conXLSClsName as String = "XLMain"

'Variable to hold the app's window handle
Dim lngXLSHandle as Long

'Get the applications window handle, unconcerned with the windows name.
lngXLSHandle = FindWindow(conXLSClsName, 0)

'Using the window handle returned by "FindWindow" use the "GetWindowThreadProcessId" (declared as stated above by paulbent) to get a single thread of a running application and/or the applications process id.

'The following code will return only a single thread of the window application.

'Variable to hold thread id
Dim lngThreadId as Long

'Get a applications thread id (single instance)
lngThreadId = GetWindowThreadProcessId(lngXLSHandle, 0)

The problem I was having was that I was unable to close the running program with just the single instance of the thread id. This was, as I found out later, because the application may, and normally does, have multiple thread instances active during it’s processing. Therefore, killing just one of these instances would not completely close the application as I needed. Not to mention some of the inadvertent damage killing a single thread of an application can do in comparison to killing the process itself. I mainly use the FindWindow to determine if a particular application is running in the back ground, this is helpful when your application may need a particular application either opened or closed in order for it to run properly.

paulbent provided an exceptional way of killing a process, when needed, using the window handle that I got from the "FindWindow" function.


ERM
 
EnS,

Thanks again for the help. I have worked with API calls enough to understand the basics. Your post was very helpful. Where I got hosed was not knowing to use XLMain for the Class name. I tried everything I could think of but never thought of XLMain. Where do I look to find that Excel's class name is XLMain?

Have a great day!

Have a great day!

j2consulting@yahoo.com
 
Here's a small list that I have:

Class Name Application

SciCalc CALC.EXE
CalWndMain CALENDAR.EXE
Cardfile CARDFILE.EXE
Clipboard CLIPBOARD.EXE
Clock CLOCK.EXE
CtlPanelClass CONTROL.EXE
XLMain EXCEL.EXE
Session MS-DOS.EXE
Notepad NOTEPAD.EXE
pbParent PBRUSH.EXE
Pif PIFEDIT.EXE
PrintManager PRINTMAN.EXE
Progman PROGMAN.EXE (Windows Program manager)
Recorder RECORDER.EXE
Reversi REVERSI.EXE
#32770 SETUP.EXE
Solitaire SOL.EXE
Terminal TERMINAL.EXE
WFS_Frame WINFILE.EXE
MW_WINHELP WINHELP.EXE
#32770 WINVER.EXE
OpusApp WINWORD.EXE
MSWRITE_MENU WRITE.EXE


ERM
 
Oh, and if you're interested:

OUTLOOK rctrl_renwnd32

ERM
 
Interesting you should mention Outlook, because that's next up on my plate. THANKS TO BOTH OF YOU!

Have a great day!

j2consulting@yahoo.com
 
I found this at
I modified it to output to a message box. The piece I was missing was that you can leave the class empty and it will find it based on the Window title.

From
Option Explicit

'How can I activate an application with the Windows Classname?
'The VB AppActivate statement falls hopelessly short of being truly
'useful since the window title of an application can change without
'notice. A much more reliable means of activating another application
'is by using the window class name. It's much more reliable because
'the class name of a window will not change once the application has
'been installed. So, you ask, how do I get the class name of another
'application? You can find the window class name for any application
'by running a few lines of code. This is a one-time-only procedure.

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function GetClassName Lib "user32" Alias _
"GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long

Private Declare Function ShowWindow Lib "user32" _
(ByVal hwnd As Long, ByVal nCmdShow As Long) As Long

Const SW_SHOWNORMAL = 1
Const gcClassnameMSWord = "OpusApp"
Const gcClassnameMSExcel = "XLMAIN"
Const gcClassnameMSIExplorer = "IEFrame"
Const gcClassnameMSVBasic = "wndclass_desked_gsk"
Const gcClassnameNotePad = "Notepad"
Const gcClassnameMyVBApp = "ThunderForm"

Public Sub GetClassNameFromTitle()
Dim sInput As String, lpClassName As String
Dim nMaxCount As Long, lresult As Long, hwnd As Long
nMaxCount = 256
lpClassName = Space(nMaxCount)
sInput = InputBox("Enter the exact window title:" + Chr$(13) + Chr$(10) + "Note: must be an exact match")
hwnd = FindWindow(vbNullString, sInput)
If hwnd = 0 Then
MsgBox "Couldn't find the window."
Else
lresult = GetClassName(hwnd, lpClassName, nMaxCount)
MsgBox "Window: " + sInput + Chr$(13) + Chr$(10) + "Classname: " + Left$(lpClassName, lresult)
Debug.Print sInput & ": " & Left$(lpClassName, lresult)
End If
End Sub

'Run GetClassNameFromTitle and, if you enter the window title correctly,
'the class name will be shown in a messagebox. Once you have the window
'class name, you can always get a window handle by using FindWindow with
'the class name and vbNullString. For example:

' hwnd = FindWindow("OpusApp", vbNullString)

'...will find the hWnd for the Microsoft Word window.
'You can now activate the Word window with this function:

Public Function fActivateWindowClass(psClassname As String) As Boolean
Dim hwnd As Long
hwnd = FindWindow(psClassname, vbNullString)
If hwnd > 0 Then
ShowWindow hwnd, SW_SHOWNORMAL
fActivateWindowClass = True
End If
End Function








Have a great day!

j2consulting@yahoo.com
 
Hello Paul,

In the code you were kind enough to post above, what other constants are available to you for OpenProcess? And where is this stuff documented? I'm not afraid to dig in and search but I don't even know where to begin looking?

Thanks again for your code and the very helpful links!

Have a great day!

j2consulting@yahoo.com
 
Do you have a MSDN CD? If not there's MSDN Online. You can search for the name of an API function to get more info and if you're lucky a VB code example.

Paul Bent
Northwind IT Systems
 
Hi,

I'm having a similar prolem to this, i need to close IE, with Word embeded into it. I am using the command: WM_CLOSE with the PostMessage command, but the trouble is that it will ask me if i want to save any changes that have been made to the document, which i need to stop.

Is there a way of achieving this at all?

Thanks

muzz

p.s: See thread707-679667 for more info
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top