Nazgulled Posted June 21, 2007 Posted June 21, 2007 I came across this: http://www.xtremevbtalk.com/showthread.php?t=114019 And it's almost exactly what I want, the problem is, it's Legacy VB and I need it for VB.NET... Is there a module with these memory functions in VB.NET? I tried to convert them but I got no luck and when I fixed an error, another one popped up... Can anyone help me? Quote
Administrators PlausiblyDamp Posted June 22, 2007 Administrators Posted June 22, 2007 Have you looked at http://www.pinvoke.net - there are an awful lot of P/Invoke declarations there. Other than that the common conversions from VB6 are normally Longs become Integers or IntPtrs and Integers become Shorts. In fact if you are using VS 2005 it even gives you a menu entry under the Tools menu to convert VB6 code that might help in converting simple Declare statements. Other than that which parts of the post are relevant as there may be an easier or an alternate way that won't involve interop and P/Invoke. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Nazgulled Posted June 22, 2007 Author Posted June 22, 2007 Have you looked at http://www.pinvoke.net - there are an awful lot of P/Invoke declarations there. No I haven't, cause I don't know exactly how to look for what I want... I know that the above code will work, cause the example used is almost what I want to do... Other than that the common conversions from VB6 are normally Longs become Integers or IntPtrs and Integers become Shorts. In fact if you are using VS 2005 it even gives you a menu entry under the Tools menu to convert VB6 code that might help in converting simple Declare statements. I'll try to convert it again and post the results here... Quote
Nazgulled Posted June 22, 2007 Author Posted June 22, 2007 This is the code from DrMemory converted to VB.NET: DrMemory.vb [VBNET]'======================================================================= ' ' drMemory - Cross-Process Memory Buffer support ' ' © 2003 "Dr Memory" ==> Jim White ' MathImagics ' Uki, NSW, Australia ' Puttenham, Surrey, UK ' ' This module contains functions that provide both WinNT and Win9x ' style cross-process memory buffer allocation, read and write ' functions. ' ' These functions are typically required when trying to use ' SendMessage to exchange data with windows in another process. ' ' '======================================================================= ' Usage guide: ' ' 1. Allocate buffer(s) in the target process ' ' xpWindow& = <<target control window handle>> ' xpBuffer& = drMemoryAlloc(xpWindow, nBytes) ' ' 2. Prepare the data to be passed to the control ' and copy it into the buffer ' ' drMemoryWrite xpBuffer, myBuffer, nBytes ' ' 3. SendMessage xpWindow, MSG_CODE, wParam, ByVal xpBuffer ' ============== ' ' 4. Extract return data ' ' drMemoryRead xpBuffer, myBuffer, nBytes ' ' (repeat 3/4 as necessary) ' ' 5. Release the buffer ' ' drMemoryFree xpBuffer ' '======================================================================= Imports System.Runtime.InteropServices Module DrMemory Private PlatformKnown As Boolean ' have we identified the platform? Private NTflag As Boolean ' if so, are we NT family (NT, 2K,XP) or non-NT (9x)? Private fpHandle As Integer ' the foreign-process instance handle. When we want ' memory on NT platforms, this is returned to us by ' OpenProcess, and we pass it in to VirtualAllocEx. ' We must preserve it, as we need it for read/write ' operations, and to release the memory when we've ' finished with it. ' For this reason, on NT/2K/XP platforms this module should only be used to ' interface with ONE TARGET PROCESS at a time. In the future I'll rewrite ' this as a class, which can handle multiple-targets, automatic allocation ' de-allocation, etc ' Private WIN As OperatingSystem = Environment.OSVersion '================== Win95/98 Process Memory functions Private Declare Function CreateFileMapping Lib "kernel32" (ByVal hFile As Integer, ByVal lpFileMappigAttributes As Integer, ByVal flProtect As Integer, ByVal dwMaximumSizeHigh As Integer, ByVal dwMaximumSizeLow As Integer, ByVal lpName As String) As Integer Private Declare Function MapViewOfFile Lib "kernel32" (ByVal hFileMappingObject As Integer, ByVal dwDesiredAccess As Integer, ByVal dwFileOffsetHigh As Integer, ByVal dwFileOffsetLow As Integer, ByVal dwNumberOfBytesToMap As Integer) As Integer Private Declare Function UnmapViewOfFile Lib "kernel32" (ByRef lpBaseAddress As Integer) As Integer Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Integer) As Integer '================== WinNT/2000 Process Memory functions Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal dwProcId As Integer) As Integer Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal flAllocationType As Integer, ByVal flProtect As Integer) As Integer Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Integer, ByVal lpAddress As Integer, ByVal dwSize As Integer, ByVal dwFreeType 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, ByRef lpNumberOfBytesWritten As Integer) As Integer Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Integer, ByVal lpBaseAddress As Integer, ByVal lpBuffer As Integer, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Integer '================== Common Platform Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Integer, ByRef lpdwProcessId As Integer) As Integer Private Declare Sub CopyMemory Lib "kernel32" (ByVal lpDest As Integer, ByVal lpSource As Integer, ByVal cBytes As Integer) Private Declare Function lstrlenA Lib "kernel32" (ByVal lpsz As Integer) As Integer Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Integer) As Integer Private Declare Function GetClassName Lib "user32" (ByVal hwnd As Integer, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer Public Declare Function GetParent Lib "user32" (ByVal hwnd As Integer) As Integer ' ---------- Const PAGE_READWRITE As Short = &H4S Const MEM_RESERVE As Integer = &H2000 Const MEM_RELEASE As Integer = &H8000 Const MEM_COMMIT As Integer = &H1000 Const PROCESS_VM_OPERATION As Short = &H8S Const PROCESS_VM_READ As Short = &H10S Const PROCESS_VM_WRITE As Short = &H20S Const STANDARD_RIGHTS_REQUIRED As Integer = &HF0000 Const SECTION_QUERY As Short = &H1S Const SECTION_MAP_WRITE As Short = &H2S Const SECTION_MAP_READ As Short = &H4S Const SECTION_MAP_EXECUTE As Short = &H8S Const SECTION_EXTEND_SIZE As Short = &H10S Const SECTION_ALL_ACCESS As Boolean = CBool(STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE) Const FILE_MAP_ALL_ACCESS As Boolean = SECTION_ALL_ACCESS Public Function drMemoryAlloc(ByVal xpWindow As Integer, ByVal nBytes As Integer) As Integer ' ' Returns pointer to a share-able buffer (size nBytes) in target process ' that owns xpWindow ' Dim xpThread As Integer ' target control's thread id Dim xpID As Integer ' process id If WindowsNT() Then xpThread = GetWindowThreadProcessId(xpWindow, xpID) drMemoryAlloc = VirtualAllocNT(xpID, nBytes) Else drMemoryAlloc = VirtualAlloc9X(nBytes) End If End Function Public Sub drMemoryFree(ByVal mPointer As Integer) If WindowsNT() Then VirtualFreeNT(mPointer) Else VirtualFree9X(mPointer) End If End Sub Public Sub drMemoryRead(ByVal xpBuffer As Integer, ByVal myBuffer As Integer, ByVal nBytes As Integer) If WindowsNT() Then ReadProcessMemory(fpHandle, xpBuffer, myBuffer, nBytes, 0) Else CopyMemory(myBuffer, xpBuffer, nBytes) End If End Sub Public Sub drMemoryWrite(ByVal xpBuffer As Integer, ByVal myBuffer As Integer, ByVal nBytes As Integer) If WindowsNT() Then WriteProcessMemory(fpHandle, xpBuffer, myBuffer, nBytes, 0) Else CopyMemory(xpBuffer, myBuffer, nBytes) End If End Sub Public Function WindowsNT() As Boolean ' return TRUE if NT-like platform (NT, 2000, XP, etc) If Not PlatformKnown Then GetWindowsVersion() WindowsNT = NTflag End Function Public Function WindowsXP() As Boolean ' return TRUE only if XP If Not PlatformKnown Then GetWindowsVersion() WindowsXP = NTflag And (WIN.Version.MinorRevision <> 0) End Function Public Sub GetWindowsVersion() If WIN.Platform = PlatformID.Win32NT Then NTflag = True PlatformKnown = True ElseIf WIN.Platform = PlatformID.Win32Windows Then PlatformKnown = True End If End Sub '============================================ ' The NT/2000 Allocate and Release functions '============================================ Private Function VirtualAllocNT(ByVal fpID As Integer, ByVal memSize As Integer) As Integer fpHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, CInt(False), fpID) VirtualAllocNT = VirtualAllocEx(fpHandle, 0, memSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE) End Function Private Sub VirtualFreeNT(ByVal MemAddress As Integer) Call VirtualFreeEx(fpHandle, MemAddress, 0, MEM_RELEASE) CloseHandle(fpHandle) End Sub '============================================ ' The 95/98 Allocate and Release functions '============================================ Private Function VirtualAlloc9X(ByVal memSize As Integer) As Integer fpHandle = CreateFileMapping(&HFFFFFFFF, 0, PAGE_READWRITE, 0, memSize, vbNullString) VirtualAlloc9X = MapViewOfFile(fpHandle, CInt(FILE_MAP_ALL_ACCESS), 0, 0, 0) End Function Private Sub VirtualFree9X(ByVal lpMem As Integer) UnmapViewOfFile(lpMem) CloseHandle(fpHandle) End Sub Public Function dmWindowClass(ByVal hWindow As Integer) As String Dim className As String Dim cLen As Integer className = New String(Chr(0), 64) cLen = GetClassName(hWindow, className, 63) If cLen > 0 Then className = Left(className, cLen) dmWindowClass = className End Function End Module[/VBNET] Quote
Nazgulled Posted June 22, 2007 Author Posted June 22, 2007 And the rest of the code is the following. The program compiles and runs but it doesn't work as expected. Program.vb [VBNET]Imports System.Runtime.InteropServices Imports TrayTest.Common Module Program Public Const WM_USER As Short = &H400S Public Const TB_GETBUTTON As Integer = (WM_USER + 23) Public Const TB_BUTTONCOUNT As Integer = (WM_USER + 24) Public Const TB_COMMANDTOINDEX As Integer = (WM_USER + 25) Public Const TB_GETBUTTONTEXTA As Integer = (WM_USER + 45) Public Sub Main() Dim hWndTray As IntPtr = GetToolbarWindowHandle() GetToolbarButtons(hWndTray) End Sub Private Function GetToolbarWindowHandle() As IntPtr Dim hWnd As IntPtr hWnd = User32.FindWindow("Shell_TrayWnd", Nothing) hWnd = User32.FindWindowEx(hWnd, Nothing, "TrayNotifyWnd", Nothing) hWnd = User32.FindWindowEx(hWnd, Nothing, "SysPager", Nothing) hWnd = User32.FindWindowEx(hWnd, Nothing, "ToolbarWindow32", Nothing) Return hWnd End Function Private Sub GetToolbarButtons(ByVal hWndTray As IntPtr) Dim bInfo As TBBUTTON Dim xpBuffer As Integer Dim bText As String Dim tbCount As Integer Dim lret As Integer ' Get button count tbCount = User32.SendMessage(hWndTray, TB_BUTTONCOUNT, 0, 0) If tbCount <= 0 Then Exit Sub ' Need a buffer? Ask Dr Memory! xpBuffer = drMemoryAlloc(CInt(hWndTray), 4096) For tbIndex As Integer = 0 To tbCount - 1 ' TB_GETBUTTON User32.SendMessage(hWndTray, TB_GETBUTTON, tbIndex, xpBuffer) drMemoryRead(xpBuffer, VarPtr(bInfo), Len(bInfo)) lret = User32.SendMessage(hWndTray, TB_GETBUTTONTEXTA, bInfo.idCommand, xpBuffer) If lret > 0 Then bText = New String(Chr(0), lret + 1) drMemoryRead(xpBuffer, VarPtr(bText), lret) Else bText = "" End If Next drMemoryFree(xpBuffer) End Sub Private Function VarPtr(ByVal o As Object) As Integer Dim GC As GCHandle = GCHandle.Alloc(o, GCHandleType.Pinned) Dim vAddress As IntPtr = GC.AddrOfPinnedObject GC.Free() Return Marshal.ReadInt32(vAddress) End Function End Module[/VBNET] User32.vb [VBNET]Imports System.Runtime.InteropServices Namespace Common #Region " Strcuture Declarations " <StructLayout(LayoutKind.Sequential)> _ Friend Structure TBBUTTON Public iBitmap As Integer Public idCommand As Integer Public fsState As Byte Public fsStyle As Byte Public bReserved1 As Byte Public bReserved2 As Byte Public dwData As Integer Public iString As Integer End Structure #End Region #Region " API Declarations " Friend Class User32 <DllImport("user32.dll")> _ Public Shared Function SendMessage( _ ByVal hWnd As IntPtr, _ ByVal msg As Integer, _ ByVal wParam As Integer, _ ByVal lParam As Integer) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Public Shared Function FindWindow( _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As IntPtr End Function <DllImport("user32.dll", CharSet:=CharSet.Unicode)> _ Public Shared Function FindWindowEx( _ ByVal hwndParent As IntPtr, _ ByVal hwndChildAfter As IntPtr, _ ByVal lpszClass As String, _ ByVal lpszWindow As String) As IntPtr End Function End Class #End Region End Namespace[/VBNET] What code program do and what's supposed to do: First, it will find the systray (notification area) window handler, count all the toolbar buttons (icons in the systray) and then get the text (tooltip) from each button and store it in bText. The tooltip value isn't saved, the code just loops through every button, get's the text and does nothing with it. This is what the code is supposed to do. Everything works except the part to get the tooltip text from the button. I don't understand why but bInfo is always "empty" (zeros in most values). Any suggestions? Quote
Administrators PlausiblyDamp Posted June 23, 2007 Administrators Posted June 23, 2007 Could you attach the project as a zip file (just remove the binaries first) and I'll try and see what is happening on this pc. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Nazgulled Posted June 24, 2007 Author Posted June 24, 2007 Here it is... The variable bText is supposed to get the tooltip from each systray icon (doesn't do anything with it, but while debugging I checked and there was only an empty string). Also bInfo values should have some values in each structure element but they are all the same through the button loop and almost all zeros. Hope you find a way to sort it out, I must be doing something wrong...TrayTest.zip Quote
shaii Posted October 27, 2007 Posted October 27, 2007 Hi, Does any one know the solution for this one? I'm facing the same problem. cheers, s. Quote
Recommended Posts