|
-
Jul 14th, 2002, 11:00 AM
#1
GetWindowWord help please
I have the code to return a file name/path for a window:
''''''''''''
Dim ModuleName As String, FileName As String, hInst As Long, hWnd As Long
ModuleName = String$(128, Chr$(0))
hWnd = FindWindow("class name", vbNullString)
hInst = GetWindowWord(hWnd, GWW_HINSTANCE) ' -6
ModuleName = Left$(ModuleName, GetModuleFileName(hInst, ModuleName, Len(ModuleName)))
MsgBox ModuleName
'''''''''
However this always returns the path of my program, and NOT the window i want.
hWnd returns a number, no problem there.
But hInst always returns 0.
I think this is the problem, (maybe GWW_HINSTANCE is wrong?), any ideas would be great.
Thanks, David.
-
Jul 14th, 2002, 11:17 AM
#2
Addicted Member
The procedure for getting an EXE name from a window is pretty well known now, here's my version:
Code:
Option Explicit
' =================================================================
' Section 1: OS-dependent stuff (Task/Process Enumeration)
' =================================================================
' W95/98 specific
Private Const MAX_PATHLEN = &H104
Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
exeFilename(1 To MAX_PATHLEN) As Byte
End Type
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal dprocess As Long) As Long
Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, pProcessEntry As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, pProcessEntry As PROCESSENTRY32) As Long
Private Const TH32CS_SNAPPROCESS = &H2&
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
'
' NT specific
' Note that some returned parameters (ProcessId, hModule) are actually
' arrays but as we call with one request at a time a single Long var
' reference is sufficient.
'
Private Declare Function EnumProcesses Lib "psapi" (ProcessId As Long, ByVal cbSize As Long, cbReturned As Long) As Long
Private Declare Function EnumProcessModules Lib "psapi" (ByVal ProcessId As Long, hModule As Long, ByVal cbSize As Long, cbReturned As Long) As Long
Private Declare Function GetModuleBaseName Lib "psapi" Alias "GetModuleBaseNameA" (ByVal hProcess As Long, ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private Declare Function GetModuleFileNameEx Lib "psapi" Alias "GetModuleFileNameExA" (ByVal hProcess As Long, ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
'
' Version, ProcessId detection
'
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Private Const PROCESS_QUERY_INFORMATION = &H400& ' for OpenProcess
Private Const PROCESS_VM_READ = &H10& ' for OpenProcess
Function ExePathFromWindow(ByVal hWindow As Long) As String
Dim ProcessId As Long, hProcess As Long
'
' The only thing Nt and 95/98 have in common is this!
Call GetWindowThreadProcessId(hWindow, ProcessId)
ExePathFromWindow = ExePathFromProcessId(ProcessId)
End Function
Function ExePathFromProcessId(ByVal ProcessId As Long) As String
Dim hProcess As Long
'
If Not IsWindowsNT Then ' Win2000 is included
Dim Process As PROCESSENTRY32, hSnap As Long, f As Long, Exename$
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0&)
If hSnap = -1 Then Exit Function
Process.dwSize = Len(Process)
f = Process32First(hSnap, Process)
Do While f <> 0
If Process.th32ProcessID = ProcessId Then
GoSub GetExeName
ExePathFromProcessId = Exename ' strZtoStr(process.exeFilename)
Call CloseHandle(hSnap)
Exit Function
End If
Process.dwSize = Len(Process)
f = Process32Next(hSnap, Process)
Loop
Else
Dim s As String, c As Long, hModule As Long
Const cMaxPath = 1023
s = String$(cMaxPath, 0)
hProcess = ProcessHandleFromProcessId(ProcessId)
hModule = BaseModuleHandleFromProcessId(ProcessId)
c = GetModuleFileNameEx(hProcess, hModule, s, cMaxPath)
' c = GetModuleBaseName(hProcess, hModule, s, cMaxPath)
If c Then ExePathFromProcessId = Left$(s, c)
End If
Exit Function
GetExeName:
Dim i&, cb As Byte
Exename = ""
Do While i < MAX_PATHLEN
i = i + 1
cb = Process.exeFilename(i)
If cb = 0 Then Return
Exename = Exename & Chr$(cb)
Loop
Return
End Function
Private Function IsWindowsNT() As Boolean
Dim verinfo As OSVERSIONINFO
verinfo.dwOSVersionInfoSize = Len(verinfo)
If (GetVersionEx(verinfo)) = 0 Then Exit Function
If verinfo.dwPlatformId = 2 Then IsWindowsNT = True
End Function
Function ProcessHandleFromProcessId(ProcessId As Long)
ProcessHandleFromProcessId = _
OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, ProcessId)
End Function
Function BaseModuleHandleFromProcessId(ProcessId As Long)
Dim hModule As Long, hProcess As Long, bReturned As Long
hProcess = ProcessHandleFromProcessId(ProcessId)
Call EnumProcessModules(hProcess, hModule, 4&, bReturned)
BaseModuleHandleFromProcessId = hModule
End Function
Adapt it as you wish....
Dr Memory (currently in sunny!! Surrey)
Last edited by MathImagics; Aug 14th, 2002 at 12:34 PM.
"He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king"  ("The Rock'n'Roll Doctor", Lowell George)
"If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)
-
Jul 14th, 2002, 11:43 AM
#3
Yea you are right! I am sitting here with the doors open next to me and getting the heat. About time we had some nice weather, i was beginning to think England had forgotten about summer this year.
Anywaaaay....back to the topic.
Thanks for the info, do u have declarations for all of the API calls as im struggling to find them all, there seem to be rather a lot. And this "Dim Process As PROCESSENTRY32," says user defined type not defined.
Thanks again. (Btw this work on 98, 2000 and XP?)
-
Jul 14th, 2002, 12:54 PM
#4
Mostly done, exceptm i can not find API declarations for these 2:
hProcess = ProcessHandleFromProcessId(ProcessId)
'hModule = BaseModuleHandleFromProcessId(ProcessId)
also this gives an error:
cb = Process.exeFilename(i)
Method or data member not found.
-
Jul 14th, 2002, 01:27 PM
#5
Addicted Member
Apologies - I'll track down the missing bits and pieces and get them to you.
Yes it should work on all platforms - there are 2 basic flavours, NT and non-NT - I'll include a function that can decide which one you are on ...
Godalmighty, it's Sunday in Godalming.....
Cheers
Dr Memory
"He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king"  ("The Rock'n'Roll Doctor", Lowell George)
"If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)
-
Jul 14th, 2002, 01:56 PM
#6
Addicted Member
OK, I've replaced the code segment in my earlier post - it is now a fully-functional self-contained module that exports ExePathFromWindow...
Cheers
Dr Memory
"He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king"  ("The Rock'n'Roll Doctor", Lowell George)
"If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)
-
Jul 14th, 2002, 02:09 PM
#7
Many thanks.
Hey, if u r stuck indoors on this lovely day at least uve helped some1 out
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|