'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.

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
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.
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
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
-chris
XiaoFeng
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
-chris
yassir
~~~~~~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
Private Declare Function GetWindowThreadProcessId Lib "user32.dll"
(ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
Regards,
-chris
StevenBerr
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
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 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.