none
Problem with GetModuleFileNameEx

    Question

  • I am new to the Window's API and have been trying to just poke around with it.  It was suggested to me to try making a time tracker program that will track how long a window is actively being used and keep windows from the same .exe file grouped together.  Things have been going good so far, but I am having trouble with the GetModuleFileNameEx command.

    According to MSDN if GetModuleFileNameEx succeeds it should return the length of the path name; however, when I output the return value of GetModuleFileNameEx, it is just a random long number that changes with every tick of the timer.
    Also when i try to output the path of the open window just to see what is being stored there, it is blank.  I have googled and surfed the net for help but to no avail.  I was curious if someone here might have an answer for me

    Here is the code I am having trouble with:
    Public Class Form1
    
        'Windows API functions
        Private Declare Function GetForegroundWindow Lib "user32.dll" () As System.IntPtr
        Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" ( _
            ByVal hWnd As System.IntPtr, _
            ByVal lpString As System.Text.StringBuilder, _
            ByVal nMaxCount As Integer) As Integer
        Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
            ByVal hwnd As System.IntPtr, _
            ByRef lpdwProcessId As Long) As Long
        Declare Function GetModuleFileNameEx Lib "psapi.dll" Alias "GetModuleFileNameExA" ( _
            ByVal hProcess As Long, _
            ByVal lpFilename As System.Text.StringBuilder, _
            ByVal nSize As Long) As Long
    
    
    
    
            ' Recieves the handle of the foreground window
         nextWnd = GetForegroundWindow()
    
            ' Gets title and path of the active window
         GetWindowText(nextWnd, lpString, lpString.Capacity)
         GetWindowThreadProcessId(nextWnd, procID)
         modTest = GetModuleFileNameEx(procID, lpFileName, lpFileName.Capacity)

    lblTest.Text = modTest.ToString()


    Thanks in advance,
    ~John
    Thursday, June 25, 2009 3:51 PM

Answers

  • Well...  Probably because the signature you have is for GetModuleFileName not GetModuleFileNameEx :)  I guess I should have looked at the documentation for the function first...

    Private Declare Function GetModuleFileNameEx Lib "psapi.dll" ( _
            ByVal hProcess As System.IntPtr, _
            ByVal hModule As System.IntPtr, _
            ByVal lpFilename As System.Text.StringBuilder, _
            ByVal nSize As Integer) As Integer
    
    
    Just pass IntPtr.Zero to the hModule parameter.

    HTH
    Tom Shelton
    • Proposed as answer by jinzai Saturday, June 27, 2009 9:02 PM
    • Marked as answer by Yichun Feng Wednesday, July 01, 2009 1:53 AM
    Friday, June 26, 2009 4:09 AM

All replies

  • There are a few problems with your declares that may be tripping you up:

    1)  Long in VB.NET is 64-bit.  You should be declaring those as Integer (this is most likely the cause of your problem).
    2)  You don't need the alias's
    3)  You aren't using IntPtr for some of your handles (ProcessId, for example).

    Here is how I would declare these functions:
    Private Declare Function GetForegroundWindow Lib "user32.dll" () As System.IntPtr
    
    Private Declare Auto Function GetWindowText Lib "user32.dll" ( _
            ByVal hWnd As System.IntPtr, _
            ByVal lpString As System.Text.StringBuilder, _
            ByVal nMaxCount As Integer) As Integer
    
    Private Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
            ByVal hwnd As System.IntPtr, _
            ByRef lpdwProcessId As System.IntPtr) As System.IntPtr
    
    Private Declare Function GetModuleFileNameEx Lib "psapi.dll" ( _
            ByVal hProcess As System.IntPtr, _
            ByVal lpFilename As System.Text.StringBuilder, _
            ByVal nSize As Integer) As Integer
    
    Anyway, the pushing of the long value (64-bit) where a 32-bit value was expected is probably unbalancing the stack and giving you strange results.

    HTH
    Tom Shelton
    Thursday, June 25, 2009 4:37 PM

  • Hmmm, well i changed it, and like you said it was a 64-bit Vs 32-bit problem, however is there  reason that it would not be returning a path?  Now it outputs 0 as if its working correctly, so i do not know why it will not find a filepath to the .exe.


    ~John
    Thursday, June 25, 2009 6:43 PM
  • Well...  Probably because the signature you have is for GetModuleFileName not GetModuleFileNameEx :)  I guess I should have looked at the documentation for the function first...

    Private Declare Function GetModuleFileNameEx Lib "psapi.dll" ( _
            ByVal hProcess As System.IntPtr, _
            ByVal hModule As System.IntPtr, _
            ByVal lpFilename As System.Text.StringBuilder, _
            ByVal nSize As Integer) As Integer
    
    
    Just pass IntPtr.Zero to the hModule parameter.

    HTH
    Tom Shelton
    • Proposed as answer by jinzai Saturday, June 27, 2009 9:02 PM
    • Marked as answer by Yichun Feng Wednesday, July 01, 2009 1:53 AM
    Friday, June 26, 2009 4:09 AM
  • Hi,

    It is probably the best to take the answers from Tom about API's, but when you want to find it first yourself next time

    http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html






    Success
    Cor
    Friday, June 26, 2009 6:27 AM