Solved

GetModuleHandle & GetModuleUsage

Posted on 1997-06-02
27
256 Views
Last Modified: 2009-07-29
Hello !

Is it anyone who can help me whith this:
I like to know if a file is running on the machine.
In VB3 i did use it like this but it won´t work now in 32-bit.  
    X = GetModuleHandle("C:\Windows\System\tapiexe.exe") X = GetModuleUsage(X)
If X <> 0 Then  'The Program runs
   
Do anyone know how to find out that a file runs in 32-bit ?
Janne Andersson, Nyköping Sweden

Mail:         janne.a@mailbox.swipnet.se
0
Comment
Question by:jannea
  • 12
  • 9
  • 6
27 Comments
 
LVL 2

Expert Comment

by:vorlon
ID: 1426734
Jannea,
Here's one way that will work. Cycle throught the task list. As you do, check the name of the file of the current application with the name of the file you're looking for. Here's an example.

This example checks to see of c:\windows\calc.exe (Calculator) is running.

Sub Command1_Click ()
    Const neededFile = "c:\windows\calc.exe"
    Dim hInstance As Variant, hWnd As Variant
    Dim fname As String
    Dim x As Integer

    'get first window
    hWnd = GetWindow(Form1.hWnd, GW_HWNDFIRST)
    Do
        'get handle of window
        hInstance = GetWindowWord(hWnd, GWW_HINSTANCE)

        'get name of exe file running
        fname = String(256, 0)
        x = GetModuleFileName(hInstance, fname, Len(fname))

        'compare running app with what were looking for
        If LCase$(Left$(fname, x)) = LCase$(neededFile) Then
            'yes, the exe file were interested in is running
            MsgBox neededFile & " found"
        End If

        'get the next window from the task list
        hWnd = GetWindow(hWnd, GW_HWNDNEXT)

    'keep looping until there's no more app's in the task list
    Loop Until hWnd = 0
End Sub


Hope this helps.
0
 
LVL 1

Author Comment

by:jannea
ID: 1426735
Hello Vorlon, and thanks for your answer !

But i can´t find the value for the constant GWW_HINSTANCE.
so i did use the GWL_HINSTANCE = -6 instead, and
hwnd = GetWindow(Screen.ActiveForm.hwnd, GW_HWNDFIRST)
I don´t know if this works but the only application i can se running is VB5 the one i run it from.
What can be wrong i have several app´s running.

/Janne
0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426736
Testa GetWindowLong istället för GetWindowWord och se om det fungerar. Jag tror det är det L respektive W står för i GWL_HINSTANCE.

/ Andreas
0
 
LVL 2

Expert Comment

by:vorlon
ID: 1426737
Jannea,
You use GW_HWNDFIRST for only the first call. All subsequent calls to GetWindow() you have to use GW_HWNDNEXT. Also, I used the handle of the main window in my application. I don't know if using Screen.ActiveForm.hwnd works simply because the active window can be a dialog box. GetWindow usually only returns parent windows unless you specifically ask for child windows.

Try that and see how it works.
Hope this helps.


0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426738
Jodå, nu har jag testat det, och det är minsann lösningen på problemet. Får jag nån poäng för det? :-)

/ Andreas
0
 
LVL 1

Author Comment

by:jannea
ID: 1426739
This time i get several files by changing to
GetWindowLong(hwnd, GWL_HINSTANCE)
as Andreas comment (Tack du...).
But... i can´t understand what i get oute of this
it lists same file several times, some are blank and it seems
to be only the files VB5 uses.
I even run several exe´s but i can´t see them in the loop.
Send the result of my loop and my code.

This is the result of the my loop line by line:

C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE


C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE

C:\PROGRAM\VANLIGA FILER\MICROSOFT SHARED\VBA\MSO97RT.DLL
C:\PROGRAM\VANLIGA FILER\MICROSOFT SHARED\VBA\MSO97RT.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VBA5.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VBA5.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\RPCRT4.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\VB5\VBA5.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\WINDOWS\SYSTEM\OLEAUT32.DLL
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\WINDOWS\SYSTEM\RPCRT4.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLEAUT32.DLL
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\WINDOWS\SYSTEM\RPCRT4.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\VB5\VB5.EXE
C:\PROGRAM\VANLIGA FILER\MICROSOFT SHARED\VBA\MSO97RT.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE


C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\WINDOWS\SYSTEM\SHELL32.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE




C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\WINDOWS\SYSTEM\OLE32.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\WINDOWS\SYSTEM\MSVBVM50.DLL
C:\VB5\VB5.EXE
C:\VB5\VB5.EXE

104 lines.




Sub KörsFil()
Const neededFile = "c:\windows\calc.exe"
Dim hInstance As Variant, hwnd As Variant
Dim fname As String
Dim X As Integer
Dim Y%, s$

'get first window
    s = "This is the result of the my loop:" & vbCrLf
    hwnd = GetWindow(Screen.ActiveForm.hwnd, GW_HWNDFIRST)
    Do
'get handle of window
         hInstance = GetWindowLong(hwnd, GWL_HINSTANCE)
'get name of exe file running
        fname = String(256, 0)
        X = GetModuleFileName(hInstance, fname, Len(fname))
        Y = Y + 1
        s = s & fname & vbCrLf
'compare running app with what were looking for
        If LCase$(Left$(fname, X)) = LCase$(neededFile) Then
'yes, the exe file were interested in is running
            MsgBox neededFile & " found"
        End If
'get the next window from the task list
        hwnd = GetWindow(hwnd, GW_HWNDNEXT)

'keep looping until there's no more app's in the task list
    Loop Until hwnd = 0
    s = s & Y & " st instanser." & vbCrLf
    MsgBox s
End Sub

Any new ideas ??????

/Janne
0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426740
Verkar som du har rätt i det. Jag testade bara och konstaterade att det dök upp annat än VB i rutan. Vad är det för program du ska kolla efter? Skulle du kunna kolla på något annat än exe-filens namn, t.ex. namn på fönster eller fönsterklass?
0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426741
Här är en funktion som nog kan användas: CreateToolhelp32Snapshot

Tyvärr har jag mycket att göra just nu, så jag kan inte skriva ner nåt exempel, och jag är inte helt säker på att den fungerar med VB, men det kan kanske vara värt ett försök.
0
 
LVL 2

Expert Comment

by:vorlon
ID: 1426742
Y96andha,
What language are you speacking. I'm getting something that is not english.

Jannea,
I'll confirm the code again. This time I'll use my VB4 compiler. I'll let you know if I get the same problem as you...
0
 
LVL 1

Author Comment

by:jannea
ID: 1426743
Re: Andreas (y96andha)

It would be nice if you could give me codesample on
CreateToolhelp32Snapshot, so i can see if that works better
then the sample above.
If not Vorlon can give me a solotion on my problem.
I write in english so evev Vorlon can understand.

/Janne
0
 
LVL 1

Author Comment

by:jannea
ID: 1426744
RE Vorlon
y96andha have givenen me comments in Swedish.

I use VB5 and i just like to know if a specific file is
loaded *.exe or *.dll as you can see above i don´t get
what i like to get oute of the loop.

/Janne
0
 
LVL 2

Expert Comment

by:vorlon
ID: 1426745
Jannea,
Swedish? Pretty interesting...

Anyway, found some information for you. I don't have a 32 bit compiler with me at this time so you'll have to try this yourself or wait until I get home tonight.

hWnd = GetWindow(Form1.hWnd, GW_HWNDFIRST)
In my answer above I'm using this line of code to get the first top level window. Instead of using Form1.hWnd, use the handle of the desktop window and get it's child windows. Like this:

hWnd = GetDesktopWindow()
hWnd = GetWindow(hWnd,GW_CHILD)
'or in one line
'hWnd = GetWindow(GetDesktopWindow(),GW_CHILD)
Do
 ...
Loop


This came straight out of "Visual Basic Programmer's Guide to the Win32 API" by Daniel Appleman, Chapter 5: Windows Control and Information Functions, page 180-181. It states:

"...the first of several methods for enumerating windows. It starts by obtaining the handle of the desktop window - the window that represents the entire screen. All windows in the system are considered children of the desktop - which is not the same as saying that they are child windows. It's best to think of the desktop window as a special window that provides certain special capabilities, one of which is to help you enumerate other windows in the system."

I'll confirm this at home. In the mean time, hope this helps.
0
 
LVL 1

Author Comment

by:jannea
ID: 1426746
Sorry, Vorlon

I get the same result whith:

hWnd = GetDesktopWindow()
hWnd = GetWindow(hWnd,GW_CHILD)

/Janne
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Expert Comment

by:y96andha
ID: 1426747
This time in English so everyone can read it :-)

OK, I've modified your code in the following, vorlon:

Private Sub Command1_Click()
Cls
    Dim hInstance As Variant, hwnd As Variant, hModule As Variant
    Dim fname As String
    Dim txt As String
    Dim x As Integer

    'get first window
    hwnd = GetWindow(Form1.hwnd, GW_HWNDFIRST)
    Do
    'get handle of window
    hInstance = GetWindowLong(hwnd, GWL_HINSTANCE)
    hModule = GetClassLong(hwnd, GCL_HMODULE)
    txt = String(256, 0)
   
    'get name of exe file running
    fname = String(256, 0)
    x = GetModuleFileName(hModule, fname, Len(fname))
   
    GetWindowText hwnd, txt, 256
   
    Print hModule; " "; hInstance; " FN:"; Left$(fname, InStr(fname, Chr(0)) - 1); " T:"; Left$(txt, InStr(txt, Chr(0)) - 1)

    'get the next window from the task list
    hwnd = GetWindow(hwnd, GW_HWNDNEXT)

    'keep looping until there's no more app's in the task list
    Loop Until hwnd = 0
End Sub

When you use this code you will see that there are lots of windows for which no exe is found. An example is:

1901068288   1901068288  FN: T:Experts Exchange(sm):  Visual Basic Question - Microsoft Internet Explorer
 1666711552   1666711552  FN: T:Internet Explorer

The Win32 documentation says:

The GetModuleFileName function retrieves the full path of the module associated with a handle returned by GetModuleHandle or LoadLibrary.

The GetModuleHandle function returns a module handle for the specified module if the file has been mapped into the address space of the calling process.


From this I draw a conclusion: GetModuleFileName might not work with modules loaded in other address spaces than that of the calling process.

If that is the case, then I suggest an alternative method, using a function named CreateToolhelp32Snapshot together with Process32First and Process32Next. I am not sure whether this will work under Windows NT, because it is listed under Windows 95 features, but it is the best function I've found yet.

Unfortunately I've never used any of these functions, so I figured that if someone else has, he/she could probably more easily create an example program. I have an example in C if someone's interested.


0
 
LVL 2

Expert Comment

by:vorlon
ID: 1426748
Jannea,
SORRY. It seems that win32 architecture prevents you from finding out the name (exe of dll) of a module asside from that of the current application. This would explay why you're getting a lot of Visual Basic files.

I placed you're question on a the visual basic news group. As soon  as I know something I'll pass it on to you?

(But if code in vb3, the previous answer would work, ha ha)

Again, sorry. I'll try to get you an answer as soon as possible...
0
 
LVL 1

Author Comment

by:jannea
ID: 1426749
Still waiting for a answer...

/Janne


0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426750
Tja, vorlon har ju svarat på frågan, så för inga poäng alls, eller "bara" 50 är det lite mycket jobb. Men jag skulle kunna titta lite på det.
0
 
LVL 1

Author Comment

by:jannea
ID: 1426751
Andreas:
Har inte fattat vad som händer när man kommer till ett läge där det blir låst som i denna fråga.
För att kasta ut frågan på nytt, och vad är rimligt att ge för bedömning till Vorlon ?

Har ju fortfarande inget som funkar...

/Janne
0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426752
För att kasta ut frågan på nytt och låta någon annan svara så ska du välja grade F, då kommer den åter att hamna uppe bland obesvarade frågor. Men vorlon verkar ju jobba på att få ett svar från newsgrupperna, så det kan hända att han löser det.
0
 
LVL 1

Author Comment

by:jannea
ID: 1426753
Vorlon:

Do you think you can get me some answer or should
i let someone else to try to answer it  ?

/Jannea
0
 
LVL 2

Expert Comment

by:vorlon
ID: 1426754
Jannea,
Unfortunatly, I'm still stuck. Give it to someone who can: I too would like to know how to get around the Different Module structure... I'm still working on it but might take a while.

Sorry.
0
 
LVL 1

Author Comment

by:jannea
ID: 1426755
Vorlon:

Thanks anyway and welcome to try again.
I think i have to increase the points...

/Janne
0
 
LVL 1

Author Comment

by:jannea
ID: 1426756
Adjusted points to 100
0
 
LVL 5

Accepted Solution

by:
y96andha earned 100 total points
ID: 1426757
Detta är en lösning som kräver Windows 95:

Private Const TH32CS_SNAPPROCESS = &H2
Private Const MAX_PATH = 260
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
    szExeFile As String * MAX_PATH
End Type
Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal dwFlags As Long, ByVal PID As Long) As Long
Private Declare Function Process32First Lib "kernel32" (ByVal hSnapShot As Long, pe32 As PROCESSENTRY32) As Long
Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapShot As Long, pe32 As PROCESSENTRY32) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Sub Command1_Click()
    Cls
    Dim hSnapShot As Long: hSnapShot = 0
    Dim pe32 As PROCESSENTRY32

    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
    If hSnapShot = -1 Then
        MsgBox "fel"
        Exit Sub
    End If
   
   
    pe32.dwSize = Len(pe32)
   
    If Process32First(hSnapShot, pe32) Then
        Do
            Print pe32.szExeFile
        Loop While Process32Next(hSnapShot, pe32)
    Else
        MsgBox "ingen process32first!"
    End If

    CloseHandle hSnapShot
End Sub



0
 
LVL 1

Author Comment

by:jannea
ID: 1426758
Tack för detta Andreas, det funka bra !

Vet du något smart sätt att ta bort Nulltecknen föresten ?
Det jag gjort nu verkar klumpigt !

     Do
            sE = pe32.szExeFile
            For X = 1 To Len(sE)
                If Mid$(sE, X, 1) = vbNullChar Then
                    sE = Left$(sE, X - 1): Exit For
                End If
            Next
            s = s & sE & vbCrLf
      Loop While Process32Next(hSnapShot, pe32)

Tror jag har gjort på något annat sätt tidigare men kommer inte ihåg hur. Det funkar ju inte med Trim.

"Jag tänkte som en bonus för jag gav dig Grade A."

/Janne
0
 
LVL 5

Expert Comment

by:y96andha
ID: 1426759
Jag brukar köra nåt i stil med detta. Inskrivet från minnet, men jag tror det funkar.

If Instr(pe32.szExeFile,chr(0)) Then
          sE=left$(pe32.szExeFile, Instr(pe32.szExeFile,chr(0))-1)
Else
          sE=pe32.szExeFile
End If

Om man vet att det är nulltecken i den så räcker
          sE=left$(pe32.szExeFile, Instr(pe32.szExeFile,chr(0))-1)


0
 
LVL 1

Author Comment

by:jannea
ID: 1426760
Tack för det, det var nog bättre.

Vi hörs, Janne.a@mailbox.swipnet.se
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

705 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

21 Experts available now in Live!

Get 1:1 Help Now