Results 1 to 11 of 11

Thread: confused about GetModuleFileName()

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    confused about GetModuleFileName()

    ok, i'm calling GetMOduleFileName from VB.NET. So i declared:

    VB Code:
    1. Public Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Integer, ByVal lpFileName As String, ByVal nSize As Integer) As Integer

    notice that lpFileName is passed "ByVal". Now here's the thing, lpFileName is a pointer to the buffer that will receive the null terminated string. So shouldn't it be "ByRef"? Because if it's "ByVal", the api function GetModuleFileName will be getting the value instead, right? It should be passing ByRef, yet it only works if its ByVal.

  2. #2
    PowerPoster RhinoBull's Avatar
    Join Date
    Mar 2004
    Location
    New Amsterdam
    Posts
    24,132

    Re: confused about GetModuleFileName()

    A quick quote from MSDN will clear your confusion, indeed:
    ByVal

    A way of passing the value of an argument to a procedure instead of passing the address. This allows the procedure to access a copy of the variable. As a result, the variable's actual value can't be changed by the procedure to which it is passed.

  3. #3
    PoorPoster iPrank's Avatar
    Join Date
    Oct 2005
    Location
    In a black hole
    Posts
    2,729

    Re: confused about GetModuleFileName()

    Sorry benmartin101 for posting in your thread.
    I had subscribed the thread form the day you posted.

    Rhino, I'm still confused.

    As the MSDN quote says (and we all know) when passing ByVal, the "variable's actual value can't be changed by the procedure to which it is passed".

    That means, as GetModuleFileName is getting lpFileName by value, it can't change the original string in our calling module.

    But, in fact, it fills the string with new value in our calling module.
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetModuleFileName Lib "kernel32" _
    4. Alias "GetModuleFileNameA" _
    5.       (ByVal hModule As Long, _
    6.        ByVal lpFileName As String, _
    7.        ByVal nSize As Long) As Long
    8.        
    9.        
    10. Private Declare Function GetWindowWord Lib "user32" _
    11.       (ByVal hwnd As Long, _
    12.        ByVal nIndex As Long) As Integer
    13.        
    14. Const GWW_HINSTANCE = (-6)
    15. Private Sub Form_Load()
    16.    
    17.     Dim ModuleName As String * 128, FileName As String, hInst As Long
    18.     'create a buffer
    19.     ModuleName = String(128, Chr$(0))
    20.     'get the hInstance application:
    21.     hInst = GetWindowWord(Me.hwnd, GWW_HINSTANCE)
    22.    
    23.     '--------------------------------
    24.     MsgBox "ModuleName [b]BEFORE[/b] calling GetModuleFileName : " & ModuleName
    25.     '--------------------------------
    26.     Call GetModuleFileName(hInst, ModuleName, Len(ModuleName))
    27.     '--------------------------------
    28.     MsgBox "ModuleName [b]AFTER[/b] calling GetModuleFileName : " & ModuleName
    29.     '--------------------------------
    30.    
    31. End Sub
    Last edited by iPrank; Dec 7th, 2005 at 09:43 AM.
    Usefull VBF Threads/Posts I Found . My flickr page .
    "I love being married. It's so great to find that one special person you want to annoy for the rest of your life." - Rita Rudner


  4. #4
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: confused about GetModuleFileName()

    In .NET Strings are immutable, so you would pass a StringBuilder ByRef and then call its .ToString() method to retrieve the string contents.

    VB Code:
    1. Imports System.Runtime.InteropServices
    2.  
    3. <DllImport("kernel32", EntryPoint:="GetModuleFileNameW")> Private Shared Function GetModuleFileName ( _
    4.     ByVal hModule As Integer, _
    5.     <MarshalAs(UnmanagedType.LPWStr)> ByRef lpFilename As StringBuilder, _
    6.     ByVal nSize As Integer _
    7. ) As Integer

  5. #5
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: confused about GetModuleFileName()

    @ iPrank - this is VB.NET, it's different. Strings in VB6 are not classes, they are just pointers to BSTRs which are string buffers. The buffer content CAN be changed. In VB.NET the String class is immutable, that means the buffer content CANNOT be changed.

    Also, since we are using ByVal with a string, a futher caveat applies. In VB6 when you pass a string ByVal to an API function, VB makes a temporary ANSI buffer from your original Unicode string, and passes a pointer to that buffer to the API function. When the function returns the buffer is converted back to Unicode into your original string.

    If you use the -W Unicode API functions instead, you declare it ByVal ... As Long, and use StrPtr(stringname) to pass a pointer to the Unicode buffer directly. That saves all the conversion stuff.

    However, if you use ByVal to pass a string WITHIN your VB application, a Unicode copy is made. Therein lies the difference.

  6. #6
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: confused about GetModuleFileName()

    Quote Originally Posted by benmartin101
    It should be passing ByRef, yet it only works if its ByVal.
    I missed this part. In that case it is because you are calling the ANSI version of the function, so the same Unicode->ANSI->Unicode marshalling takes place as in VB6, which is why it works. If you use DllImport it allows you to specify Charset:=Charset.Unicode which means no Unicode->ANSI conversion will take place. Alternatively, if you must use the Declare syntax, you can use the Unicode keyword on it (Private Declare Unicode Function).

  7. #7
    PoorPoster iPrank's Avatar
    Join Date
    Oct 2005
    Location
    In a black hole
    Posts
    2,729

    Re: confused about GetModuleFileName()

    Quote Originally Posted by penagate
    @ iPrank - this is VB.NET, it's different.
    OOPS !

    Thanks for your reply.
    Usefull VBF Threads/Posts I Found . My flickr page .
    "I love being married. It's so great to find that one special person you want to annoy for the rest of your life." - Rita Rudner


  8. #8

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    Re: confused about GetModuleFileName()

    still a bit confused. Tell me, in this code:

    VB Code:
    1. Public Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Integer, ByVal lpFileName As String, ByVal nSize As Integer) As Integer
    is lpFileName's address or value being send to the function? Now, the way I see it, the address is being passed, even though its ByVal.

    And in this code:

    VB Code:
    1. Public Function Func1(ByVal x As String)
    2. x = "Hello"
    3. end function
    is x's address or value being passed? To me, x is being passed by value.

  9. #9

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    Re: confused about GetModuleFileName()

    I just tried this out in c#:

    [DllImport("kernel32")]
    extern static int GetModuleFileName(int hMod, String lpFilename, int size);

    and it doesn't work, but if I change String to StringBuilder, then it works, how come?

  10. #10
    I'm about to be a PowerPoster!
    Join Date
    Jan 2005
    Location
    Everywhere
    Posts
    13,647

    Re: confused about GetModuleFileName()

    I've explained why it passes the address even with ByVal.
    when you pass a string ByVal to an API function, VB makes a temporary ANSI buffer from your original Unicode string, and passes a pointer to that buffer to the API function. When the function returns the buffer is converted back to Unicode into your original string.
    and also about StringBuilder
    In VB.NET the String class is immutable, that means the buffer content CANNOT be changed.
    which is why you use StringBuilder instead, which is NOT immutable.

  11. #11

    Thread Starter
    Frenzied Member
    Join Date
    Jul 2005
    Posts
    1,168

    Re: confused about GetModuleFileName()

    oh ok, i got it now. Thanks.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width