romiebehunin
asked on
VB.NET System.AccessViolationException: Attempted to read or write protected memory.
Hey guys... This has had me stumped all day so I figured I'd get some expert advise. I have a program that is doing some basic form screen scraping using API calls. Once I start reading in the various text elements on the child form, after about 10 iterations I get the following error:
System.AccessViolationExce ption: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at CaptureTextTest.Form1.Enum ChildWindo ws(Int32 hWndParent, EnumChildWindProc lpEnumFunc, Int64 lParam)
at CaptureTextTest.Form1.Butt on3_Click( Object sender, EventArgs e) in C:\... Form1.vb: line 140
I read that there was a hot fix for this issue: http://support.microsoft.com/?kbid=923028 but it does not seem applicable as I'm running .Net 3.5 SP1 on the machine in question. I've attached the code in full.
System.AccessViolationExce
at CaptureTextTest.Form1.Enum
at CaptureTextTest.Form1.Butt
I read that there was a hot fix for this issue: http://support.microsoft.com/?kbid=923028 but it does not seem applicable as I'm running .Net 3.5 SP1 on the machine in question. I've attached the code in full.
Option Strict Off
Option Explicit On
Imports System.Windows.Forms.Application
Imports System.Threading.Thread
Imports System.Runtime.InteropServices
Public Class Form1
Public hWnd As Long
Public obj As New TCaptureXLib.TextCaptureX
Public strResults As String
Public strWinTitle As String
Public lhWndP As Long
Public strCaption As String
Public blnCustomScrape As Boolean
Private strMyScrape As String
<DllImport("user32", EntryPoint:="GetWindowTextLength")> _
Private Shared Function GetWindowTextLength( _
ByVal hwnd As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="FindWindow")> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindowText")> _
Private Shared Function GetWindowText( _
ByVal hwnd As Int32, _
ByVal lpString As System.Text.StringBuilder, _
ByVal cch As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="GetWindow")> _
Private Shared Function GetWindow( _
ByVal hwnd As Int32, _
ByVal wCmd As Int32) As Int32
End Function
Private Const GW_HWNDNEXT As Int32 = 2
Private Declare Function BringWindowToTop Lib "user32" (ByVal _
hwnd As Long) As Long
Private Const WM_GETTEXT As Integer = &HD
Private Const WM_GETTEXTLENGTH As Integer = &HE
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Integer
Private Declare Function SendMessage2 Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As Integer
Delegate Function EnumChildWindProc(ByVal hWnd As Int32, ByVal lParam As Long) As Boolean
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Int32, ByVal lpEnumFunc As EnumChildWindProc, ByVal lParam As Long) As Long
Private Sub CaptureWindow(ByVal hWnd)
strResults = ""
Do Until Not strResults = ""
BringWindowToTop(hWnd)
strResults = obj.CaptureActiveWindow()
If strResults <> "" Then
RichTextBox1.Text = strResults
End If
QuickRefresh(250)
Loop
'GetHandle()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RichTextBox1.Clear()
GetHandle()
End Sub
Private Function GetHandleFromPartialCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
GetHandleFromPartialCaption = False
'Get the parent window using API
lhWndP = FindWindow(vbNullString, vbNullString)
'Get the child window here
If lhWndP <> 0 Then
End If
Do While lhWndP <> 0
Dim iStr As Integer = GetWindowTextLength(lhWndP) + 1
Dim sStr As New System.Text.StringBuilder(iStr)
GetWindowText(lhWndP, sStr, iStr)
strCaption = sStr.ToString
If InStr(1, strCaption, sCaption) > 0 Then
GetHandleFromPartialCaption = True
lWnd = lhWndP
Exit Do
End If
lhWndP = GetWindow(lhWndP, GW_HWNDNEXT)
Loop
End Function
Private Sub QuickRefresh(ByVal i As Integer)
DoEvents()
Sleep(i)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
End
End Sub
Private Sub GetHandle()
If GetHandleFromPartialCaption(lhWndP, "Practice Plus") = True Then
'MsgBox("Found Window Handle: " & lhWndP, vbOKOnly + vbInformation)
If blnCustomScrape = False Then
CaptureWindow(lhWndP)
End If
Else
MsgBox("Window 'Horizon' was not found", vbOKOnly + vbExclamation)
End
End If
QuickRefresh(250)
End Sub
Private Function GetWindowText(ByVal hWnd As IntPtr) As String
Dim textLength As Integer = SendMessage2(hWnd, WM_GETTEXTLENGTH, 0, 0) + 1
Dim sb As New System.Text.StringBuilder(textLength)
If textLength > 0 Then
Call SendMessage(hWnd, WM_GETTEXT, textLength, sb)
End If
Return sb.ToString
End Function
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
blnCustomScrape = True
GetHandle()
Try
Dim proc As New EnumChildWindProc(AddressOf EnumChildWindow)
Call EnumChildWindows(lhWndP, proc, 0&) 'This is the call that generates error
Catch ex As Exception
ex = ex
MsgBox(ex.ToString)
End
End Try
End Sub
Function EnumChildWindow(ByVal hChild As Int32, ByVal lParam As Long) As Boolean
Dim wText As New System.Text.StringBuilder(255)
Dim j As Long
j = GetWindowText(hChild, wText, 255)
j = j
'I get about 10 text elements from
'the child form before the error takes place
strMyScrape = strMyScrape + wText.ToString
EnumChildWindow = 1 ' Continue enumeration
End Function
End Class
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Excellent suggestion... did the trick!! Thank You!!
ASKER