vb6 convertion

I am porting a project from vb6 to vb.net 2005 and I cannot figure out one convertion.

'This Function gets the text of the window
Private Function GetText(Get_hWnd As Long) As String
Dim lenTxt As Long, retText As String
lenTxt = GetWindowTextLength(Get_hWnd) + 1
retText = String$(lenTxt, " ")
GetWindowText Get_hWnd, retText, lenTxt
GetText = retText
End Function

The bold function is what I cannot figure out. I know the String function is the following:

String Function

String(number, character)

Returns a Variant of subtype String that is of the length specified by number and is filled with a given character.


But I do not know the equivalent of it in vb.net. Any help would be greately appreciated. This is the only function that I couldn't port. Thank you.




Answer this question

vb6 convertion

  • JamesChan

    Well, the problem I think is that any of the following:

    1. You are writting managed type to unmanaged address pointer.
    2. WriteProcessMemory is expecting an address of buffer for its third parameter to work.

    Both can be solved by the Marshal class' Writexx methods:




    ' Write a byte to memory
    System.Runtime.InteropServices.Marshal.WriteByte(address, 0, CByte(90))

    ' Write a word to memory
    System.Runtime.InteropServices.Marshal.WriteInt16(myHeap, 0, CShort(9090))

    ' Write a integer to memory
    System.Runtime.InteropServices.Marshal.WriteInt32(myHeap, 0, 909090)




    For list of available methods in Marshal class, see here:
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfsystemruntimeinteropservicesmarshalmemberstopic.asp

    Regards,

    -chris



  • StephenGB

    It is an external process. I get the process handle and id via the window's handle. I can send you my project via email or messenger if it would make it easier to find out what I am doing wrong.


  • angelbear

    Hi,

    A couple of issues here:

    1. When you are returning a result in VB.NET, you need to use the Return keyword, assigning FunctionName=Result is no longer supported by VB.NET:

    Use:



    Return retText

     


    Instead of:


    GetText = retText

     


    2. Long datatype in VB6 represent a 32bit signed integer. In VB.NET, Integer is already a 32bit signed integer, and Long represents 64bit signed integer. Hence, you have to replace Long to Integer (conversion wizards is unable to change those):

    Use:


    Dim My32Bit As Integer

     


    Instead of:


    Dim My32Bit As Long

     


    3. Strings in VB.NET are immutable, meaning you can't change its value without recreating it. Passing a ByRef to an API function to retrieve string result is not advicable, use System.Text.StringBuilder class instead:

    Use:


    Dim retText As New System.Text.StringBuilder
    GetWindowText(Get_hWnd, retText, lenTxt)

     


    Instead of:


    Dim retText As String
    GetWindowText(Get_hWnd, ByRef retText, lenTxt)

     


    With all the conversion issues I mentioned, the resulting (corrected) function is now:




    ' API Declarations
    Private Declare Function GetWindowTextLength
     Lib "user32.dll"
     Alias "GetWindowTextLengthA"
      (ByVal hwnd As IntPtr) As Integer

    Private Declare Function GetWindowText
     Lib "user32.dll"
     Alias "GetWindowTextA"
      (ByVal hwnd As IntPtr,
      ByVal lpString As System.Text.StringBuilder,
      ByVal cch As Integer) As Integer

    ' GetText corrected function
    Private Function GetText(ByVal Get_hWnd As IntPtr) As String
            Dim retText As New System.Text.StringBuilder
            Dim lenTxt As Integer = GetWindowTextLength(Get_hWnd) + 1
            GetWindowText(Get_hWnd, retText, lenTxt)
     Return retText.ToString()
    End Function

     


    Hope this helps,

    -chris



  • C.Z.

    Ok so I have the following:

    Private Function GetText(ByVal Get_hWnd As Long) As String
    Dim lenTxt As Long, retText As String, s As New System.Text.StringBuilder
    lenTxt = GetWindowTextLength(Get_hWnd) + 1
    retText = s(lenTxt)
    GetWindowText(Get_hWnd, retText, lenTxt)
    GetText = retText
    End Function

    The thing is s only accepts one argument. The tooltip says: Chars(index As Integer) As Char
    I have no idea why it only accepts one argument, or even why the argument it accepts is Char.



  • farah

     


    1. When you are returning a result in VB.NET, you need to use the Return keyword, assigning FunctionName=Result is no longer supported by VB.NET:

    Whilst I agree that using the return keyword is the VB.Net convention setting the functionname= result would still work and is provided for legacy reasons.

    Declares is the only VB6 way of using API calls, System.Runtime.InteropServices.DllImport attribute is the new .NET way.

     

    The code your looking for is as follows, which shows the declarations and a usage of the function.

    Public Class Form1

        <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
       Private Shared Function GetWindowText(ByVal hwnd As IntPtr, _
                              ByVal lpString As System.Text.StringBuilder, _
                              ByVal cch As Integer) As Integer

        End Function

        <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
        Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
        End Function


        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim i As IntPtr
            i = Me.Handle

            Me.label1.text = GetText(i)
        End Sub


        Public Function GetText(ByVal hWnd As IntPtr) As String
            Dim length As Integer
            If hWnd.ToInt32 <= 0 Then
                Return Nothing
            End If
            length = GetWindowTextLength(hWnd)
            If length = 0 Then
                Return Nothing
            End If
            Dim sb As New System.Text.StringBuilder("", length + 1)

            GetWindowText(hWnd, sb, sb.Capacity)
            Return sb.ToString()
        End Function
    End Class


  • jlawing

    The string$ will create a fixed length string of lentxt number of characters - in this LenTxt would be an integer so its basically creating a fixed length string of spaces

    dim s as string = String$(LenTxt, " ") ' VB6

    Dim s As New System.Text.StringBuilder(" ", LenTxt) '//VB.NET



  • uhduh

    Is the process you are trying to write, the same as your calling process Or is it an external process

    -chris

  • XiaoFeng

    The following code worked perfect in vb6 but isn't working in .net.

    Call WriteAInt(&H41825E, &H909090, 3)

    Here is WriteAInt:

    Public Sub WriteAInt(ByVal Address As Integer, ByVal Value As Integer, ByVal ByteLength As Integer)
    WriteProcessMemory(phandle, Address, Value, ByteLength, 0&)
    End Sub

    The problem is that it writes 000000 to the address instead of 909090.


  • Brent Rector

    Thanks for the information spotty.

    -chris

  • yassir

    Hmm...That worked perfectly. Thanks. I am going to post my module code in case it has more errors please let me know. Thanks.

    ~~~~~~DeclareAPI - Module~~~~~~

    Module DeclareAPI
    Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
    (ByVal hwnd As Integer, _
    ByVal lpClassName As String, _
    ByVal nMaxCount As Integer) As Integer

    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal classname As String, _
    ByVal WindowName As String) As Integer

    Private Declare Function OpenProcess Lib "kernel32" _
    (ByVal dwDesiredAccess As Integer, _
    ByVal bInheritHandle As Integer, _
    ByVal dwProcessId As Integer) As Integer

    Private Declare Function GetWindowThreadProcessId Lib "user32" _
    (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer

    Private Declare Function WriteProcessMemory Lib "kernel32" _
    (ByVal hProcess As Integer, _
    ByVal lpBaseAddress As Integer, ByVal lpBuffer As Integer, _
    ByVal nSize As Integer, ByVal lpNumberOfBytesWritten As Integer) As Integer

    Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
    (ByVal hwnd As Integer, _
    ByVal lpString As System.Text.StringBuilder, _
    ByVal cch As Integer) As Integer

    Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" _
    (ByVal hwnd As Integer) As Integer

    Private Const PROCESS_ALL_ACCESS As Integer = &H1F0FFF
    Public WinName As String, classname As String, wtitle As String
    Public myHwnd As Integer, whandle As Integer, pid As Integer, phandle As Integer

    'This sub gets loaded first
    Public Sub Initialize()

    WinName = "Oasis"
    whandle = FindWindow(vbNullString, WinName)
    myHwnd = FindWindow(vbNullString, Form1.Text)

    classname = Space$(255)
    Call GetClassName(whandle, classname, Len(classname))

    If CBool(InStr(1, classname, vbNullChar)) Then
    classname = Left$(classname, InStr(1, classname, vbNullChar) - 1)
    End If

    wtitle = GetText(CType(whandle, IntPtr))
    If (whandle <> 0) Then GetWindowThreadProcessId(whandle, pid)
    phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)

    End Sub

    'This Function gets the text of the window
    Private Function GetText(ByVal Get_hWnd As IntPtr) As String
    Dim retText As New System.Text.StringBuilder
    Dim lenTxt As Integer = GetWindowTextLength(CInt(Get_hWnd)) + 1
    GetWindowText(CInt(Get_hWnd), retText, lenTxt)
    Return retText.ToString()
    End Function

    'This Sub writes the values to memory
    Public Sub WriteAInt(ByVal Address As Integer, ByVal Value As Integer, ByVal ByteLength As Integer)
    WriteProcessMemory(phandle, Address, Value, ByteLength, 0&)
    End Sub

    End Module


    ~~~~~~DeclareAPI - Module~~~~~~



  • jrenton87

    On your API declaration, try adding the ByRef keyword to lpdwProcessId parameter of GetWindowThreadProcessId:



    Private Declare Function GetWindowThreadProcessId Lib "user32.dll"
     (ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer

     


    Regards,

    -chris

  • StevenBerr

    Hmm...That helped immensely. Thank you very much. It seems you know alot about either vb6 or APIs.

    Actually, changing all of my API functions arguments from long to integer fixed all of the PInvoke problems I was having.

    Would you mind taking a look at my source to see if I need to convert anything else. The source is small enough to post but I could send it to you via email. Let me know what you think.



  • kpoon

    I tried the following:

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    System.Runtime.InteropServices.Marshal.WriteInt32(&H41825E, 0, 909090)
    End Sub

    It didn't seem to work. Do you think it would have something to do with the way I am accessing the process (my API calls)



  • Philipp Lenz

    I just ran into another problem. My program is not finding the window's process id or handle.
    I am using the following:

    If (whandle <> 0) Then GetWindowThreadProcessId(whandle, pid)
    phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)


    where: whandle is the window's handle, pid is the processID, phandle is the process handle and PROCESS_ALL_ACCESS is a constant that equals &H1F0FFF

    Now, the program is not causing any errors but it does not get the pid or phandle (they equal 0 on load). Please note that whandle does not equal zero.

    Thanks.


  • vb6 convertion