Verwendung WM_COPYDATA lässt VB6 Anwendung abstürzen

14/07/2008 - 15:38 von Denise | Report spam
Hallo,

ich habe das Problem, dass meine vb6-Anwendung, die daten über WM_COPYDATA
von einer c# Anwendung erhàlt, nach dem Eingang von einer bes. Anzahl von
Meldungen abstürzt. Dieser fehler kommt dann:
"Anwendung hat ein Problem
festgestellt und muss beendet werden." in der Ereignisanzeige unter Anwendung
findet man die Fehlermeldung: Fehlgeschlagene Anwendung, fehlgeschlagenes
Modul kernel32.dll.
Es hat was mit der Anzahl der Meldungen zu tun. Wie als würde 'was
volllaufen'.
Wenn ich nur alle 4 Sekunden Daten übertrage, tritt der Fehler nach 48
Stunden auf; bei einer Datenübertargung alle 2 Sekunden bereits nach 24
Stunden.

Hier mein Code:

' Formular wird initialisiert mit Handle für datenaustausch
Public Sub InitForm()
Handle = Me.hwnd

lpPrevWndProc = SetWindowLong(Handle, GWL_WNDPROC, _
AddressOf WindowProc)

Me.Caption = CAPTION_MDE
End Sub

' Funktion für Erhalt der Meldung
' DataExchanger ist eigene Klasse, die daten verarbeitet
Public Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal
wParam As Long, ByVal lParam As Long) As Long
If uMsg = WM_COPYDATA Then
Call dataExchanger.ReceiveData(lParam)
End If
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End Function


' Methode die von c#-Praogramm gesendeten Daten verarbeitet
Public Sub ReceiveData(lParam As Long)
Dim cds As COPYDATASTRUCT
Dim buf(1 To 255) As Byte
Dim telegram As String
Dim subStrings As Variant

Call CopyMemory(cds, ByVal lParam, Len(cds))

Call CopyMemory(buf(1), ByVal cds.lpData, cds.cbData)
telegram = StrConv(buf, vbUnicode)
telegram = Left$(telegram, InStr(1, telegram, Chr$(0)) - 1)


subStrings = Split(telegram, "###")

' Wenn subStrings untersucht wurden -acknowledge
SendAcknowledge()

End Sub

' Sendet Bestàtigung für Erhalt der neuen Nachricht
Private Sub SendAcknowledge()

Dim cds As COPYDATASTRUCT
Dim ThWnd, i As Long
Dim buf(1 To 255) As Byte
Dim message As String

' Handle für MA auslesen
ThWnd = FindWindow(vbNullString, CAPTION_MA)

If ThWnd = 0 Then
' Fehler
Else
' Meldung die gesendet wird
message = "1"

' Copy the string into a byte array, converting it to ASCII
Call CopyMemory(buf(1), ByVal message, Len(message))
cds.dwData = 3
cds.cbData = Len(message) + 1
cds.lpData = VarPtr(buf(1))

'Meldung senden
i = SendMessage(ThWnd, WM_COPYDATA, frmHandle.hwnd, cds)
End If
End Sub

Kann hier jemand erkennen, wo der fehler liegt; wo ich evtl. Speicher
reserviere und nicht mehr freigebe.

Danke,

Grüße Denise
 

Lesen sie die antworten

#1 Juergen Thuemmler
14/07/2008 - 17:09 | Warnen spam
ich habe das Problem, dass meine vb6-Anwendung, die daten über WM_COPYDATA
von einer c# Anwendung erhàlt, nach dem Eingang von einer bes. Anzahl von
Meldungen abstürzt.


<->

SendMessage() kehrt erst dann zum Aufrufer zurück, wenn die verarbeitende
Prozedur beim Empfànger vollstàndig abgearbeitet ist. Bis dahin ist der
Sender "suspended". Deshalb sollte man in der Empfàngerprozedur (hier
WindowProc() bzw. ReceiveData()) nur das Allernotwendigste tun und die
Funktion schnellstmöglich zurückkehren lassen. Das Allernotwendigste ist in
diesem Fall, den String zu gewinnen. Ich würde deshalb "telegram" als
modulglobale Variable deklarieren und nach
telegram = Left$(telegram, InStr(1, telegram, Chr$(0)) - 1)


eine Weiterverarbeitung anschubsen und die Funktion verlassen. Die
Weiterverarbeitung kann in einer Timerprozedur erfolgen (dann wird nach der
Stringgewinnung der Timer (Interval = 10) enabled) oder noch besser über ein
PostMessage() an das eigene Fenster mit eindeutigem Parameter nach der
Stringgewinnung.
Keinesfalls darf man aus der verarbeitenden Prozedur wieder ein
SendMessage() an den Sender aufrufen. Eigentlich müßte da ein
Deadlock-Zustand entstehen, da ja der Sender die Message gar nicht
verarbeiten kann, da er ja noch suspended ist...
Generell sollte man "SendMessage()" nur dann verwenden, wenn es zwingend
notwendig ist, wie beispielsweise für WM_COPYDATA. Für einfache
Benachrichtigungen wie für SendAcknowledge() ist PostMessage() oder auch
SendNotifyMessage() wesentlich besser geeignet.
Ich verwende WM_COPYDATA sehr hàufig und habe deshalb eine kleine Dll
geschrieben, die das làstige und nicht ganz ungefàhrliche Subclassen
vermeidet; siehe
http://allapi.mentalis.org/vbexampl...irc;LLBACK

Jürgen.

Ähnliche fragen