| |
VB.NET - Ein- und UmsteigerVB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Vaubehnet | Datum: 20.03.17 13:47 |
| Hallo zusammen,
ich arbeite mich gerade in die Übergabe von Werten zwischen Formularen ein; dabei stoße ich auf eine Fehlermeldung (s.u.), für die ich keine Lösung finde, zumal das nur im Dialog zwischen diesen beiden Forms auftritt, nicht aber bei anderen Formularen meiner Anwendung, die vergleichbar gebaut sind:
Formular 1: "frmGruppen" mit einer Listbox "lstGruppen" und einem Button "btnAuswaehlen_Click";
letzterer öffnet ein zweites Formular und übergibt Werte.
Formular 2: "frmSQL"; dieses enthält ebenfalls eine Listbox, mehrere Textboxen, Buttons und eine Richttextbox.
Das Formular "frmSQL" wird normal geöffnet, die Daten korrekt angezeigt, ich kann zunächst arbeiten.
Wenn ich aber in "frmSQL" auf eine Textbox klicke, erhalte ich eine Fehlermeldung in der Routine des Buttons "btnAuswählen_Click" des 1. Formulars.
Fehlermeldung: "Zusätzliche Informationen: Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist."
Der Wert des "frmSQL" ist: frmSQL {BEST_Control.frmSQL, Text: SQL-Statements editieren} BEST_Control.frmSQL
Da die restliche Anwendung einwandfrei läuft, will ich das mit dem geschützten Speicher nicht so einfach glauben...
Code des Buttons "btnAuswaehlen_Click":
Private Sub btnAuswaehlen_Click(sender As Object, e As EventArgs) Handles _
btnAuswaehlen.Click
'--------------------------
'Formular SQL-Editor öffnen
'--------------------------
Dim intID As Integer = 0
Dim strGruppeBezeichnung As String = ""
intID = Me.lstGruppen.SelectedItem.value
strGruppeBezeichnung = Me.lstGruppen.SelectedItem.key
Dim frmSQL As New frmSQL(intID, strGruppeBezeichnung)
'Formular aufrufen
'Hier tritt der Fehler auf, wenn ich im 2. Formular (frmSQL) auf eine Textbox
' klicke!
frmSQL.ShowDialog()
End Sub Hier der Code des zweiten Formulars:
Imports System.Windows.Forms
Public Class frmSQL
Private Access As New DBAccess
Private Oracle As New dbOracle
Private intID As Integer 'ID der Gruppe
Private strBezeichnung As String
Public Sub New(intID As Integer, strBezeichnung As String)
' Dieser Aufruf ist für den Designer erforderlich.
InitializeComponent()
' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf
' hinzu.
Me.intID = intID
Me.lblGruppe.Text = strBezeichnung
'... weiterer Code
End Sub Ich hoffe, Ihr könnt mir helfen,
vielen Dank,
Vaubehnet
---
Verwendete Programmversionen:
Windows 7 64 bit sowie Windows 10 Prof.
Visual Studio 13 Professional
Microsoft Prof. 2010 (= Version 14) | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Kuno60 | Datum: 20.03.17 22:16 |
| Hallo,
in deinem Codeausschnitt ist kein Fehler erkennbar.
Die Fehlermeldung kommt von einer AccessViolationException.
Zitat:
Eine Zugriffsverletzung tritt bei nicht verwaltetem oder unsicherem Code auf, wenn der Code versucht, in Speicher zu schreiben oder zu lesen, der nicht belegt wurde oder auf den der Code keinen Zugriff hat. Die Ursache hierfür ist i. d. R. ein Zeiger, der einen ungültigen Wert aufweist. Da jedoch nicht jeder Lese- oder Schreibvorgang mit ungültigem Zeiger zu einer Zugriffsverletzung führt, weist das Auftreten einer Zugriffsverletzung darauf hin, dass mehrere Lese- oder Schreibvorgänge mit ungültigen Zeigern ausgeführt wurden und der Speicher möglicherweise beschädigt wurde. Somit sind Zugriffsverletzungen i. d. R. ein Hinweis auf schwerwiegende Fehler in der Programmierung. In .NET Framework, ab Version 2.0, werden solche Fehler durch das Auslösen einer AccessViolationException-Ausnahme eindeutig gekennzeichnet.
Es tritt also ein Problem im Zusammenhang mit nicht verwaltetem Code auf. | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Manfred X | Datum: 21.03.17 12:01 |
| Hallo!
Einige Hinweise:
Prüfe zunächst im btn_Auswählen_Click-Handler, ob ein Item in der Listbox selektiert ist.
Verwende nicht den Klassennamen für die Bezeichnung einer Referenzvariable (frmSQL).
Insbesondere nicht bei Formularen.
Erstelle für IntID und lblGruppe.Text Properties in frmSQL und prüfe im
"Set"-Bereich der Properties die Gültigkeit der als Parameter übergebenen Angaben.
Nutze einen Using-Block für den untergeordneten Dialog. Etwa so ...
Using MySql as new frmSql
- With MySQL
-- .ID = intID
-- .Gruppe = strGruppeBezeichnung
-- .Showdialog
- End With
End Using
Dadurch wird die Instanz des untergeordneten Formulars am Dialog-Ende
rasch und sauber entsorgt.
Schau Dir die Eventhandler Deiner Textbox in frmSQL an.
Nutze eventuell Try-Catch-Blöcke um eine Ausnahme ggf. vor Ort aufzufangen.
Dort liegt vermutlich der Fehler. | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Vaubehnet | Datum: 21.03.17 13:49 |
| Hallo Kuno, hallo Manfred,
danke erst mal für Eure Kommentare.
@Manfred: Ich versuche, Deine Hinweise schrittweise umzusetzen, damit ich verstehe, was den Fehler verursacht. Hier ist die erste Adaption, die leider immer noch einen Fehler erzeugt:
(Bisherige Anpassungen aufgrund Deiner Hinweise sind im Code mit ## gekennzeichnet).
Private Sub btnAuswaehlen_Click(sender As Object, e As EventArgs) Handles _
btnAuswaehlen.Click
'--------------------------
'Formular SQL-Editor öffnen
'--------------------------
'## angepasst: Try/Catch
Try
Dim intID As Integer = 0
Dim strGruppeBezeichnung As String = ""
'## angepasst: Prüfen, ob etwas selektiert wurde:
If lstGruppen.SelectedIndex = -1 Then
MsgBox("Bitte selektieren Sie einen Eintrag aus der" & _
"Gruppenliste", vbInformation, "Fehler: Kein Eintrag" & _
"selektiert")
Exit Sub
End If
intID = Me.lstGruppen.SelectedItem.value
strGruppeBezeichnung = Me.lstGruppen.SelectedItem.key
'## angepasst: Verwende nicht den Klassennamen für die Bezeichnung
' einer Referenzvariable (frmSQL).
Dim frmOracleSQL As New frmSQL(intID, strGruppeBezeichnung)
frmOracleSQL.ShowDialog()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub Trotz Try/Catch steigt der Code nach der Bearbeitung im Folgeformular beim Showdialog-Statement aus:
'Erzeugt Fehler
frmOracleSQL.ShowDialog() Die Fehlermeldung hat sich aber verändert.
frmSQL: "frmSQL" ist ein Typ und kann nicht als Ausdruck verwendet werden.
Manfred X schrieb:
Zitat: | |
Nutze einen Using-Block für den untergeordneten Dialog. Etwa
so ...
Using MySql as new frmSql
- With MySQL
-- .ID = intID
-- .Gruppe = strGruppeBezeichnung
-- .Showdialog
- End With
End Using
Dadurch wird die Instanz des untergeordneten Formulars am
Dialog-Ende
rasch und sauber entsorgt.
| |
"Using MySql as new frmSQL" erwartet als Übergabewerte in Klammern dahinter bereits die beiden Werte für ID und strGruppeBezeichnung; daher weiß ich noch nicht, wie ich das umsetzen soll.
Dim frmOracleSQL As New frmSQL(intID, strGruppeBezeichnung) Danke u. Gruß
Vaubehnet
---
Verwendete Programmversionen:
Windows 7 64 bit sowie Windows 10 Prof.
Visual Studio 13 Professional
Microsoft Prof. 2010 (= Version 14) | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Manfred X | Datum: 21.03.17 15:02 |
| Wie Kuno60 bereits mitgeteilt hat, ist Deinem Code keine
eindeutige Fehlerbedingung zu entnehmen.
Ich würde die beiden Formulare so aufbauen:
Public Class frmTestX
Dim WithEvents btnAuswaehlen As New Button _
With {.Parent = Me}
Dim lstgruppen As New ListBox _
With {.Parent = Me, .Top = 50}
'??????
Public Class Itm
Public value As Integer
Public key As String
End Class
Private Sub frmTestX_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
Dim it As New Itm
it.key = "Gruppe1"
it.value = 1
lstgruppen.Items.Add(New Itm)
End Sub
Private Sub btnAuswaehlen_Click(sender As Object, _
e As EventArgs) Handles btnAuswaehlen.Click
Try
Dim intID As Integer = 0
Dim strGruppeBezeichnung As String = ""
If lstGruppen.SelectedIndex = -1 Then
MsgBox("Bitte selektieren Sie einen Eintrag aus der" & _
"Gruppenliste", vbInformation, "Fehler: Kein Eintrag" & _
"selektiert")
Exit Sub
End If
intID = _
DirectCast(Me.lstgruppen.SelectedItem, Itm).value
strGruppeBezeichnung = _
DirectCast(Me.lstgruppen.SelectedItem, Itm).key
Using frmOracleSQL As New frmSQL
With frmOracleSQL
'Formular-Eigenschaften zuweisen
.GroupID = intID
.GroupName = strGruppeBezeichnung
.ShowDialog()
End With
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
'Explizit erstellt Windows-Form
Public Class frmSQL
Dim lblGruppe As New TextBox With {.Parent = Me}
Private _intID As Integer 'ID der Gruppe
Private _strBezeichnung As String
Private Access As DBAccess
Private Oracle As dbOracle
Public Property GroupID As Integer
Set(value As Integer)
If value = -1 Then
Throw New ArgumentException("unzulässige GruppenID")
End If
_intID = value
End Set
Get
Return _intID
End Get
End Property
Public Property GroupName As String
Set(value As String)
If String.IsNullOrWhiteSpace(value) Then
Throw New ArgumentException("Gruppen-Name fehlt")
End If
_strBezeichnung = value
End Set
Get
Return _strBezeichnung
End Get
End Property
Private Sub frmSQL_Load(sender As Object, e As System.EventArgs) Handles _
Me.Load
Access = New dbaccess
Oracle = New dboracle
lblGruppe.Text = _strBezeichnung
End Sub
Private Class dbaccess
'Hier könnte ein Problem liegen
End Class
Private Class dboracle
'Hier könnte ein Problem liegen
End Class
End Class
Beitrag wurde zuletzt am 21.03.17 um 15:11:09 editiert. | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Manfred X | Datum: 21.03.17 16:17 |
| Es könne sich um eine Fehlerbedingung handeln, die
nicht aufgefangen werden kann.
Bei dem Versuch, z.B. auf einen nicht zugeordneten Speicherbereich zuzugreifen,
schlägt ggf. Windows direkt zu und beendet komplett den Programmlauf.
Nutzt Du Windows-API-Funktionen in Deinem Programmcode oder in Bibliotheken, auf
die in Deinem Projekt verwiesen wird? In dem Fall: Prüfe die Werte-Belegung und
die Deklaration der Funktions-Parameter.
Beitrag wurde zuletzt am 21.03.17 um 16:22:21 editiert. | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Vaubehnet | Datum: 22.03.17 13:47 |
| Hallo Manfred,
ich habe mir das Problem inzwischen einmal eingehend(er) angesehen und kann den Fehler zumindest eingrenzen.
Deine Vermutung hier hat mich auf die Spur gebracht:
Private Class dboracle
'Hier könnte ein Problem liegen
End Class Hintergrund:
Meine Anwendung ruft ein Konfigurationsprogramm auf, mit dem ich in einer ACCESS-Datenbank SQL-Statements speichere; Jede Abfrage gehört zu einer Gruppe und hat einen aussagekräftigen Titel und bei Bedarf ein Vorschaubild; die "Enduser" sehen diese Konfiguration nicht, sondern haben nur einen einfachen Dialog, über den sie diese Abfragen nach Gruppen sortiert über den Titel aufrufen; d.h. sie müssen weder das dahinter stehende SQL kennen oder verstehen. Die Abfragen selbst werden auf eine ORACLE-Datenbank abgesetzt, die wir inhaltlich nicht verändern dürfen (deshalb kann ich die SQL-Statements auch nicht direkt in eine Tabelle der ORACLE-DB speichern).
Aber auch so ist das sehr praktisch, weil die Kolleg(inn)en auf diese Weise auf Kontrollroutinen zurückgreifen können, die die eigentliche Fremdanwendung nicht bietet.
Um mir die Arbeit zu erleichtern und meinen Code übersichtlicher zu halten, habe ich nun mit einer Klasse versucht, alle Datenbankabfragen zusammenzufassen - z.B. auch für das Befüllen von Datagridviews. Vielleicht habe ich mich bei der Klassenkonstruktion auch (noch) etwas übernommen.
Die folgende - im aktuellen Fall problematische - Befehlszeile übergibt das aktuelle Formular, den Namen des zu befüllenden Datagrids sowie das Abfragestatement an die Funktion fctFillDGV (die liefert dann true oder false zurück, wenn man das für die weitere Codeverarbeitung braucht).
If Oracle.fctFillDGV(Me, Me.dgvErgebnis, strSQLStatement) = true then ... Das funktioniert in dem Formular für die Endanwender auch problemlos. Daher wollte ich das ganze für meine persönlichen SQL-Entwicklungszwecke "missbrauchen": nach Eingabe eines neuen SQL-Statements im Editor ruft ein Button ein NEUES Formular auf und übergibt an das Datagridview dort die Ergebnisse der Abfrage; das erzeugt anscheinend den Fehler, weil das Programm anscheinend die Variable für das Formular frmSQL noch "sperrt" oder sonstwie benötigt. Solange ich keine Daten über die Methode an das Datagridview übergebe, habe ich auch keine Fehlermeldung.
Dem werde ich dann noch weiter nachgehen. Jedenfalls bin ich dank Deiner Hilfe schon viel weiter.
Im Moment kann ich auf die wenn auch bequeme Zusatzfunktion noch verzichten, da ich ohnehin viel in einem externen Editor arbeite. Den Code dann via Copy-Paste in meine Anwendung zu übernehmen, ist nur ein kleiner, unerheblicher Zusatzaufwand.
Viele Grüße
Vaubehnet
---
Verwendete Programmversionen:
Windows 7 64 bit sowie Windows 10 Prof.
Visual Studio 13 Professional
Microsoft Prof. 2010 (= Version 14) | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Manfred X | Datum: 22.03.17 14:18 |
| Hallo!
Du übergibst an "fctFillDGV" jeweils ein Formular als Parameter.
Sind diese Formulare vom gleichen Typ oder von einer gemeinsamen
Basisklasse abgeleitet?
Prinzipiell ist es ein fehleranfälliger und schlecht strukturierter Programmier-Stil,
wenn ein Formular sich selbst an ein untergeordnetes Formular übergibt.
Prinzipiell sollten Klassen nicht von übergeordneten Klassen abhängig sein.
Nutze - wie gezeigt - Properties im untergeordneten Formular um Daten zu
übergeben oder abzufragen.
Das einfachste wäre vermutlich, du nutzt eine Property des Typs Datatable.
Diese Instanz wird vor dem Dialog an die Property des untergeordnete Formulars
(frmSQL) übergeben, dort nach Angaben des Benutzers mit den abgefragten Daten gefüllt
und nach Beendigung des Dialogs im übergeordneten Formular an das Grid gebunden. | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Vaubehnet | Datum: 23.03.17 11:15 |
| Manfred X schrieb:
Zitat: | | Du übergibst an "fctFillDGV" jeweils ein Formular
als Parameter.
Sind diese Formulare vom gleichen Typ oder von einer
gemeinsamen
Basisklasse abgeleitet?
Prinzipiell ist es ein fehleranfälliger und schlecht
strukturierter Programmier-Stil,
wenn ein Formular sich selbst an ein untergeordnetes Formular
übergibt.
| |
Hallo Manfred,
an die Funktion "fctFillDGV" übergebe ich jeweils das aktuelle Formular, von dem aus ich das aufrufe.
Die Idee war, von jedem Formular aus durch einen Einzeiler ein Datagridview mit Daten füllen zu können.
Eine vergleichbare Funktion formatiert dann die Daten in dem Datagridview.
Das Formular (z.B. Form1) übergibt daher nach meinem Verständnis nicht sich selbst an ein untergeordnetes Formular (z.B. Form2), sondern die Information, dass auf Form1 ein Datagridview (z.B. DGVDaten) ist, und das mit dem Ergebnis einer Abfrage gefüllt werden soll.
Eigentlich fand ich das eine ziemlich schicke Lösung, da die gesamte Datenbankzugriffsroutine in der Klasse abgewickelt wird und mein Code dadurch recht übersichtlich bleibt. Und wenn dann auch noch die Formatierung des Datagridviews in eine Unterroutine verpackt werden kann, komme ich mit zwei bis drei Zeilen Code aus und habe über die gesamte Anwendung immer das gleiche Layout.
Wie gesagt, der Ansatz ist m.E. richtig, die Umsetzung wegen fehlender Sachkunde vermutlich fehlerhaft.
Das Absturzproblem wird jetzt vermutlich durch die Mischung verursacht:
Form1 ruft Form2 auf, übergibt Werte (aktuell ohne Properties), in Form2 wird nun die Information über Form2 an die fctFillDGV übergeben und dann kracht es.
Neben Deinem Properties-Beispiel habe ich einen ähnlichen (gleichen?) Ansatz in dem Artikel hier gefunden, in dem es genau um die Übergabe von Werten aus Form1 an Form2 geht:
https://msdn.microsoft.com/de-de/library/aa289529(v=vs.71).aspx
Da werde ich micht jetzt mal durcharbeiten; danach schaue ich mir die Übergabe der Formularinformationen Richtung Klasse an. Dann erst kann ich vermutlich die Frage "gleicher Typ oder gleiche Basisklasse?" beantworten.
Viele Grüße
Vaubehnet
---
Verwendete Programmversionen:
Windows 7 64 bit sowie Windows 10 Prof.
Visual Studio 13 Professional
Microsoft Prof. 2010 (= Version 14) | |
Re: VB.NET Formularaufruf führt zu Fehler bei Klick in Textfeld | | | Autor: Manfred X | Datum: 23.03.17 12:33 |
| Hallo!
[I]An die Funktion "fctFillDGV" übergebe ich jeweils das aktuelle Formular,
von dem aus ich das aufrufe.[/I]
Das könnte die Fehlerbedingung bereits erklären.
Standardinstanzen von Formularen gibt es in VB.Net aus Gründen der
Abwärts-Kompatibilität zu früheren VB-Versionen.
Sie sollten auf keinen Fall verwendet werden (ausser vielleicht in
kleinen trivialen Programmen) !!!
Der Artikel, den Du verlinkt hast, ist in Teilen veraltet.
Deine Vorgehensweise ist nicht "schick", sondern Du baust eine
Mausefalle, die irgendwann zuschnappt und kaum durchschaubare
Fehler erzeugt.
Halte Dich an die einfache Regel:
Übergeordnete Klassen interagieren mit nachgeordneten Klassen-Instanzen
durch die Nutzung der Properties der nachgeordneten Klassen.
Nachgeordnete Klassen-Instanzen lösen bei Bedarf Ereignisse aus, die in
der übergeordneten Instanz verarbeitet werden können.
Ein zentrales Grundkonzept ist die Trennung von Controls und Datenquellen
(Datenbindung). Fülle deshalb als Datenquelle eine Datatable oder ein Dataset
in der Datenzugriffsklasse. Die entsprechende Referenz kann als Property übergeben
werden. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
Neu! sevCommand 4.0
Professionelle Schaltflächen im modernen Design!
Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Weitere InfosTipp des Monats März 2024 Dieter OtterUTF-8 Konvertierung von Dateien und StringsVB6 selbst verfügt über keine Funktionen zur UTF-8 Konvertierung von Daten. Mit Hilfe des ADODB.Stream-Objekts lassen sich diese fehlenden Funktionen aber schnell nachrüsten. Access-Tools Vol.1
Über 400 MByte Inhalt
Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB
Nur 24,95 EURWeitere Infos
|