Link to home
Start Free TrialLog in
Avatar of ncw
ncw

asked on

Exiting or Terminating a Process with no window

I can use lHwnd = GetWindow(lHwnd, GW_HWNDNEXT) to get the handle to a process's window and then use that handle in either of the following lines of code and it works ok:

bRet = PostMessage(lHwnd, WM_CLOSE, 0&, 0&)
ExitProcess lHwnd
bRet = TerminateProcess(lHwnd, 0)

But how do I exit or terminate a process for which there is no window and I haven't started the process so I don't have any handle?

 
Avatar of IeuanJ
IeuanJ

if you havent started the process how can you terminate it ???
Avatar of ncw

ASKER

I am hoping to enumerate all processes running and get a handle on one of them depending on eg it's exe name.
I think you're looking to use the EnumProcesses API. API-Guide actually has a VB example of almost exactly what you're looking for.
I knew I had something somewhere.  It's not exactly what your looking for, what this does is search through all current processes to find out if the named process is running and whether it is hung or not.  Not sure if this will meet your needs but I hope it does.

----------
Call
----------
'success[boolean] = (Process_Name[string],Me[Form])
success = TaskRunning(Process_Name, Me)

'TerminateTask = (Process_Name[string])
Call TerminateTask(Process_Name)

----------
Code
----------

Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function EnumWindows Lib "user32" (ByVal wndenmprc As Long, ByVal lParam As Long) As Long ' GetWindowText used above
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long
Const GW_HWNDFIRST = 0
Const GW_HWNDNEXT = 2
Const WM_CLOSE = &H10
Const SMTO_ABORTIFHUNG = &H2
Const WM_NULL = &H0
Public msTarget As String
     
     
Public Function IsTaskHung(lCurrWnd As Long) As Boolean

    Dim lngResult As Long
    Dim lngRetVal As Long
   
    DoEvents
    lngRetVal = SendMessageTimeout(lCurrWnd, WM_NULL, 0&, _
         0&, SMTO_ABORTIFHUNG, 1000, lngResult)
    If lngRetVal Then
        IsTaskHung = False
    Else
        IsTaskHung = True
    End If
End Function

Public Function TaskRunning(sTitle As String, frmName As Form, Optional bTerminate As Boolean) As Integer
   Dim lCurrWnd As Long, lLength As Long, sTaskName As String, lParent As Long
   Dim returnInt As Integer
   returnInt = 0
   lCurrWnd = GetWindow(frmName.hwnd, GW_HWNDFIRST)
   While lCurrWnd <> 0
       lParent = GetParent(lCurrWnd)
       lLength = GetWindowTextLength(lCurrWnd)
       sTaskName = Space$(lLength + 1)
       lLength = GetWindowText(lCurrWnd, sTaskName, lLength + 1)
       sTaskName = Left$(sTaskName, Len(sTaskName) - 1)

       If lLength > 0 Then
           
           If InStr(1, UCase(sTaskName), UCase(sTitle)) <> 0 Then
               If IsTaskHung(lCurrWnd) = True Then
                   returnInt = 2
               Else
                   returnInt = 1
               End If
           End If
       End If
       lCurrWnd = GetWindow(lCurrWnd, GW_HWNDNEXT)
       DoEvents
   Wend
   TaskRunning = returnInt
End Function

Public Function EnumCallback(ByVal lAppHwnd As Long, ByVal lParam As Long) As Long
   Dim sBuf As String * 256, sTitle As String, lLength As Long
   lLength = GetWindowText(lAppHwnd, sBuf, Len(sBuf)) ' Get the window's title.
   sTitle = Left$(sBuf, lLength)
   If InStr(sTitle, msTarget) <> 0 Then SendMessage lAppHwnd, WM_CLOSE, 0, 0 ' if this is the target window, kill the window.
   EnumCallback = 1 ' Continue searching.
End Function

Public Sub TerminateTask(sAppName As String)
   msTarget = sAppName
   EnumWindows AddressOf EnumCallback, 0
End Sub
Avatar of ncw

ASKER

IeuanJ: I have similar code but it relies on having a window caption.

dankennedy: The AllApi Guide example for EnumProcesses unfortunately only includes code for NT and I'm using Win98. See http://www.allapi.net/apilist/EnumProcesses.shtml#

In the above example the following line seems to get the handle:
lngHwndProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, lngProcessIDs(lngLoop))

Just needs to be adapted for Win98. If the code for NT is run on Win98 it fails at the following line:
lngReturn = EnumProcesses(lngProcessIDs(1), lngCBSize, lngCBSizeReturned)
Avatar of ncw

ASKER

EnumProcesses function requires the PSAPI.DLL library, I don't believe Win98 has this installed. I see that kernel32 library on Win98 contains the function OpenProcess.

Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal blnheritHandle As Long, ByVal dwAppProcessId As Long) As Long
you want to do it on 98 ???  Good luck, I've only tried it on NT/2000 so far.
ncw:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
Experts: Post your closing recommendations!  Who deserves points here?
Avatar of ncw

ASKER

Didn't find a solution to ending a process on Win98 so I propose that this question be deleted
Avatar of DanRollins
ncw, an EE Moderator will handle this for you.
Moderator, my recommended disposition is:

    Refund points and save as a 0-pt PAQ.

DanRollins -- EE database cleanup volunteer
ASKER CERTIFIED SOLUTION
Avatar of YensidMod
YensidMod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial