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 wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Obtaining Hwnd from a windowed Process with ProcessID 1

Status
Not open for further replies.

krushpof

Programmer
Jul 4, 2003
72
CA

I've made a program that includes the ability to run multiple programs from the Form.Now, I use CreateProcessA to start it, but this only gives me a Struct of the ThreadID and ProcessID as return value.Now,if I want to close the process,I have no problems,using one of these two IDs are enough.

But now, I want to be able to know if a programs already running(Actually I'm already able to know this,since I keep an array of Exestarter class I made, and from there know if one of the available process was started or not).But if this process already running,I want to have its window to be brought back on top.

This is where I need to find the Hwnd.I have tried the following method to run through the processes running,but these api function seem to be running in a infinite loop.

Here's what I use:

Code:
Private Function gethWndFromProcessID(ByVal ProcessID As Long) As Long
  gethWndFromProcessID = 0
    
    Dim hwnd As Long, hWndStop As Long, hWndNext As Long, iLen, lngReply As Long
    Dim lngAssocProcessID
    
' Get a handle to the active window (first in task list).
    
    hwnd = GetActiveWindow()
    hWndStop = hwnd
    
' Loop until you reach the end of the list.
    
    Do
        
' Get the next window handle.
        hWndNext = GetNextWindow(hwnd, GW_HWNDPREV)
        
' Get the ProcessID the this window
        lngReply = GetWindowThreadProcessId(hWndNext, lngAssocProcessID)
        
' If this is the ProcessID I want set the return value and Exit.
        If lngAssocProcessID = ProcessID Then
            gethWndFromProcessID = hWndNext
            Exit Function
        End If
        
        hwnd = hWndNext
    
    Loop Until hwnd = hWndStop
    
End Function

[\code]

But it doesn't actually runs through all of the process.I don't understand.Any of you knows what might be thr problems or if there's any other way to obtain the Hwnd.

Thank you!
 

Arrrgghh,

Never mind this problem.I can't believe this.I was desperate, but now 15 minutes after calling for help I was enlighten and found my answers!!

First I was not passing the PID but some other value from the struct, which I thought was the PID but I just thought of comparing with the task manager..How silly of me I didn't think of this before.

Secondly, hWndNext = GetNextWindow(hwnd, GW_HWNDPREV)
in this function,I have to use GW_HWNDNEXT instead.Since I start with top window,I have to go forward.So when the first problem was found,this one came naturaly.


Well,Ain't it always like this.As soon as you let go,answers jumps in your face.
 
As a matter of interest, about 2 to 3 years or so ago I provided an extended variant of the ShellAndWait idea in this forum, which specifically covered a call that added the hWnd to the PROCESS_INFORMATION. Damned if I can f8nd the thread now, though...
 

That would be an interesting value for my project,Having the Hwnd directly from creation would be cpu-time savior.I'll try searching also.If you do find it,it would be great.

Thanks!
 
No, can't find the thread. But I do have the code in an archive...here's the relevant bit (you'll need to cut and paste to a module):
Code:
[COLOR=blue]
Option Explicit

Private Const WAIT_TIMEOUT = &H102

Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
                  
Private Type STARTUPINFO
   cb As Long
   lpReserved As String
   lpDesktop As String
   lpTitle As String
   dwX As Long
   dwY As Long
   dwXSize As Long
   dwYSize As Long
   dwXCountChars As Long
   dwYCountChars As Long
   dwFillAttribute As Long
   dwFlags As Long
   wShowWindow As Integer
   cbReserved2 As Integer
   lpReserved2 As Long
   hStdInput As Long
   hStdOutput As Long
   hStdError As Long
End Type

Private Type PROCESS_INFORMATION
   hProcess As Long
   hThread As Long
   dwProcessID As Long
   dwThreadID As Long
End Type

Public Type PROCESS_INFORMATION_EXT
   hProcess As Long
   hThread As Long
   hwnd As Long
   dwProcessID As Long
   dwThreadID As Long
End Type

Private Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
          
Private Const INFINITE = &HFFFF
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20

Private hWndApp As Long

Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetTopWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3

Public Function myEnumWindows(lParam As Long) As Long
    Dim hWndNext As Long
    Dim EnumerationInProgress As Boolean
    
    EnumerationInProgress = True
    hWndNext = GetTopWindow(GetDesktopWindow())
    hWndNext = GetWindow(hWndNext, GW_HWNDFIRST)
    Do While hWndNext <> 0 And EnumWindowsProc(hWndNext, lParam) <> 0
        hWndNext = GetWindow(hWndNext, GW_HWNDNEXT)
    Loop
    
End Function

Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Long
    Dim hInstance As Long
    
    EnumWindowsProc = True
    
    GetWindowThreadProcessId hwnd, hInstance
    If lParam = hInstance Then
        hWndApp = hwnd
        EnumWindowsProc = False ' End enumeration
    End If
    EnumWindowsProc = True
End Function

' Function returns slightly extended version of PROCESS_INFORMATION, containing one additional
' member, hWnd, which can be used by any API calls that require an hWnd as a parameter
' (eg SetWindowText)
Public Function RunNamedProgram(strProgram As String) As PROCESS_INFORMATION_EXT
    Dim piProcess As PROCESS_INFORMATION
    Dim siStartUp As STARTUPINFO
    Dim lResult As Long

    hWndApp = 0
    lResult = CreateProcessA(vbNullString, strProgram, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, vbNullString, siStartUp, piProcess)
    WaitForInputIdle piProcess.hProcess, INFINITE 'Let it initialise properly
    
    ' Use the first call here if running under NT4 or later. Use the second if
    ' under W9x/ME
    Call EnumWindows(AddressOf EnumWindowsProc, piProcess.dwProcessID)
    'Call myEnumWindows(piProcess.dwProcessID)
    
    RunNamedProgram.hThread = piProcess.hThread
    RunNamedProgram.hProcess = piProcess.hProcess
    RunNamedProgram.hwnd = hWndApp
    RunNamedProgram.dwProcessID = piProcess.dwProcessID
    RunNamedProgram.dwThreadID = piProcess.dwThreadID
End Function
[/color]


 
I have this thread bookmarked might it be the one you are looking for?

thread222-255803

&quot;Two strings walk into a bar. The first string says to the bartender: 'Bartender, I'll have a beer. u.5n$x5t?*&4ru!2[sACC~ErJ'. The second string says: 'Pardon my friend, he isn't NULL terminated'.&quot;
 
Aha! Yes! The reason I couldn't find it was because I'd forgotten that I'd incuded it in the wholle standard stream redirection example, so I was looking in the wrong place...
 

Thank you for this.I will definitly look into this.I don't want to simply cut and paste this, I want to understand it fully,like I always do, there's no good in simply cut&paste it.

Since I want my Exestarter class to be reusable to every program I'll need it,I'm gonna make this to be in my class.I'll also have to translate this to Delphi since I'll soon have to remake my current program with a lot of new improvement in Delphi to follow compagnie standards.

Reason it's in VB right now,it's because of a third party API that doesn't work well with Delphi.But they've just put out a com-SDK that's compatible with any Win32 ,so I don't have excuses not to follow standards.


It's ok,I like Delphi.

Anyhow,Thanks again, you've got some excellent knowledge of the Windows api.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top