Autor Beitrag
Csharp-programmierer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Do 05.11.15 20:49 
Hallo meine Experten. Ich habe mal wieder ein Problem, was meine Motivation in Sachen programmieren runterzieht :?!?: .

Ich habe ein Programm geschrieben, was in Visual Studio 2013 perfekt hinhaut. Es handelt sich um ein kleines tabellarisches Rechenprogramm. Es verfügt über eine ListView, mehreren Buttons und 3 Eingabefeldern. Wie gesagt, wenn ich in Visual Studio 2013 debugge, haut es alles hin. Nur zur Info, wie der Fehler auftritt:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
    private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListViewItem i = this.listView1.SelectedItems[0];
            this.maskedTextBox1.Text = i.Text;
            this.textBox1.Text = i.SubItems[1].Text;
            this.maskedTextBox2.Text = i.SubItems[2].Text;
        }


Wenn ich also nun verschiedene Items auswähle, ändert sich auch der Text der einzelnen TextBoxen. Das haut in Visual Studio einwandfrei, ohne Fehler hin.
Nun habe ich das Programm über die Properties in Menüreiter "Veröffentlichen" veröffentlicht. Ich habe den Installationsordner geöffnet und die Manifest Datei geöffnet. Nun wurde das Icon auf dem Desktop erstellt und das Programm ließ sich öffnen. Das Einfügen neuer Items, sowie das Speichern und das Öffnen funktionierte einwandrei. Doch dann habe ich ein Item angecklickt, so dass sich der Text der TextBoxen geändert hat. Habe ich nun ein anderes Item angeklickt, kam eine MessageBox, in der folgendes stand:

Ausnahmefehler in der Anwendung. Klicken sie auf "Weiter", um den Fehler zu ignorieren und die Anwendung fortzusetzen. Wenn sie auf "Beenden" klicken, wird die Anwendung sofort beendet,
InvalidArgument=Value mit dem Wert 0 ist für Index ungültig. Parametername: index.

Wie kann das jetzt sein, wenn in Visual Studio alles hinhaut? Ich hatte schonmal bei einem anderen Programm so einen ähnlichen Fehler. Dort wollte ich ein neues Fenster öffnen. Muss ich was bestimmtes beachten, wenn ich Programme veröffentliche? Und wie bekomme ich solche Fehler weg, die in Visual Studio nicht erkannt werden?

Mfg Yannic M.


Moderiert von user profile iconTh69: Topic aus Verteilte Systeme verschoben am Fr 06.11.2015 um 09:21
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 05.11.15 21:07 
Ich kann dir nicht sagen warum es nur in dem von dir beschriebenen Fall knallt. Eigentlich hat dein Code immer das potential zu knallen.

Du gehst einfach davon aus das immer was in SelectedItems drin ist. Das ist ein Fehlschluss. Wenn du das im Debugger offen hast, also in dem Context in dem du glaubst das es funktioniert, mach mal ein CTRL+Click auf das selektierte Item und deselektiere das damit. Jetzt hast du nix mehr selektiert und da sich die Selektion geändert hat wird SelectedIndexChanged gefeuert mit leeren SelectItems. Dein Code wird dann mit besagtem Fehler knallen.

Treffe nie solche Annahmen sowas musst du prüfen. Hier willst du wahrscheinlich das wenn nix selektiert ist auch deine anderen Controls leer sind. Also prüfe wieviel Items in SelectedItems und mach entsprechendes wenn 0,1 oder N Items drin sind.
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Do 05.11.15 21:46 
In den Items waren Daten drin. Ich wollte damit erreichen, dass der Anwender ein Item klickt und der Text säuberlich in die TextBoxen einsortiert wird.

Doch mein Problem ist, wie erkenne ich solche "Fehler", die mit im Debugger nicht angezeit werden? Was muss ich beim Programmieren beachten? Muss ich vielleicht den Release- Modus nutzen?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 05.11.15 21:59 
Zitat:
In den Items waren Daten drin. Ich wollte damit erreichen, dass der Anwender ein Item klickt und der Text säuberlich in die TextBoxen einsortiert wird.

Ja und wenn du das selbe Item nochmal klickst mit gedrückter CTRL Taste ist es wieder deselektiert und dein Code fliegt dir um die Ohren.
Zitat:
Doch mein Problem ist, wie erkenne ich solche "Fehler", die mit im Debugger nicht angezeit werden? Was muss ich beim Programmieren beachten?

Code schreiben der Fehler abfängt. Also sauberes Exceptionhandling, möglicherweise mit Loggingmöglichkeiten so das Fehler geloggt werden mit soviel Daten das man das auswerten kann.
Zitat:
Muss ich vielleicht den Release- Modus nutzen?

Debug und Release Code unterscheiden sich funktional nur minimal das wird fast nie einen Unterschied machen. Die Wahrscheinlichkeit das sich das Verhalten ändern weil ein Debugger dran hängt oder eben nicht ist da wesentlich größer. Starte doch dein Programm aus Visual Studio mal ohne Debugger und schau wie sich das verhält. (CTRL+F5 anstatt nur F5)
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Fr 06.11.15 16:16 
Vielen Dank user profile iconRalf Jansen.
Ich habe jetzt das Programm in Visual Studio gestartet ohne Debugger. Nun wird mir der selbe Fehler angezeigt. Diesen habe ich ganz einfach behoben:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
        try
            {
                ListViewItem i = this.listView1.SelectedItems[0];
                this.maskedTextBox1.Text = i.Text;
                this.textBox1.Text = i.SubItems[1].Text;
                this.maskedTextBox2.Text = i.SubItems[2].Text;
            }
            catch { }


Und jetzt funktionukkelt alles :)
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Fr 06.11.15 16:38 
Ich habe jetzt aber ein Problem in meinem Hauptprojekt (HTML-Editor). Am Anfang hat ein Boolean den Wert false. Dann erscheint ein Dialogfeld, ob das Programm Ordner erstellen darf. Danach wird der Wert dauerhaft auf true gesetzt. Der Pfad diesen Ordners wird dann auch in den Properties.Settings.Default gespeichert, wie auch der Boolean. Wenn man einen Button drückt, wird geprüft, ob der Wert einer CheckBox true ist. Trifft dies zu, wird ein String kombiniert, der den Pfad des Ordners beinhaltet. Dann werden die Datein erstellt:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
private void button8_Click(object sender, EventArgs e)
        {
            try
            {
                if ((this.textBox2.Text != null) && (this.textBox3.Text != null))
                {
                    if (this.checkBox4.Checked == true)
                    {
                        if (!Directory.Exists(Path.Combine(Properties.Settings.Default.pProjekte, this.textBox3.Text)))
                        {
                            string x = Path.Combine(Properties.Settings.Default.pProjekte, this.textBox3.Text);
                            Directory.CreateDirectory(x);
                            string bg = Path.Combine(x, "Medien");

                            if (!Directory.Exists(bg))
                            {
                                Directory.CreateDirectory(bg);
                            }

                            NeuesProjekt.Path_Neu = x;
                            Form1.HaupzPfad = Path.Combine(Properties.Settings.Default.pProjekte, this.textBox3.Text);
                            ausgabe1 = GeneriereGrundgerüst();
                            GrundgerüstEinügen1();

                            if (this.checkBox1.Checked == true)
                            {
                                CSSDateiErzeugen1();
                            }
                            if (this.checkBox2.Checked == true)
                            {
                                JSDateiErzeigen1();
                            }
                            this.Close();
                        }

                        else
                        {
                            DirectoryInfo d = new DirectoryInfo(Path.Combine(this.textBox2.Text, this.textBox3.Text));
                            MessageBox.Show("Es gibt bereits ein Projekt namens: '" + d.Name + "'. Bitte geben Sie einen anderen Namen ein.""Vergebenes Projekt", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
                        }
                    }
                    else
                    {
                        if (!Directory.Exists(Path.Combine(textBox2.Text, this.textBox3.Text)))
                        {
                            try
                            {
                                string x = Path.Combine(textBox2.Text, this.textBox3.Text);
                                Directory.CreateDirectory(x);
                                string bg = Path.Combine(x, "Medien");

                                if (!Directory.Exists(bg))
                                {
                                    Directory.CreateDirectory(bg);
                                }

                                NeuesProjekt.Path_Neu = x;

                                Form1.HaupzPfad = Path.Combine(this.textBox2.Text, this.textBox3.Text);
                                ausgabe1 = GeneriereGrundgerüst();
                                GrundgerüstEinügen1();

                                if (this.checkBox1.Checked == true)
                                {
                                    CSSDateiErzeugen1();
                                }
                                if (this.checkBox2.Checked == true)
                                {
                                    JSDateiErzeigen1();
                                }

                                this.Close();
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }
                        else
                        {
                            DirectoryInfo d = new DirectoryInfo(Path.Combine(textBox2.Text, this.textBox3.Text));
                            MessageBox.Show("Es gibt bereits ein Projekt namens: '" + d.Name + "'. Bitte geben Sie einen anderen Namen ein.""Vergebenes Projekt", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
                        }
                    }
                }
                else
                {
                    MessageBox.Show("Sie müssen einen Pfad und einen Namen des Projekts angeben.""Ungültiges Zeichen", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
                }
            }
            catch { }
        }


Gespeichert habe ich den Pfad so:
ausblenden C#-Quelltext
1:
2:
3:
4:
string s = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string y = Path.Combine(s, "Projekte");
Properties.Settings.Default.pProjekt = y;
Properties.Settings.Default.Save();


Ich habe mir den Wert der Properties per MessageBox ausgeben lassen und es kam raus: Projekte.
Im Debugger hatten die Properties aber einen vollständigen Wert.
Wie kann ich das Problem nun lösen? Ich starte die Anwendung nun immer mit Strg + F5.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 06.11.15 16:57 
Mir grauts vor deinem Code:
- Niemals try...catch{} !
- Kein Trennung von Logik und UI (Ausgabe)
- Unnötige Codeduplizierungen
- Keine ordentliche Benennung der Controls und lokalen Variablen
- ...

Aber damit du auch eine Antwort auf deine Frage erhältst: das Stichwort lautet WorkingDirectory.
Vermeide relative Dateipfadzugriffe, sondern arbeite immer von einem festen Verzeichnis aus (z.B. Application.StartupPath oder LocalAppData oder ...) und kombiniere dann ausgehend von diesem Verzeichnis alle Pfade mittels Path.Combine().
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Fr 06.11.15 17:01 
Warum sollte man kein try catch { } nehmen?
Angenommen ich würde WorkingDirectory oder Application.StartupPath nehmen, welcher Pfad wäre das?
Und warum haut das im Debugger alles hin und ohne nicht?
Greenberet
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 339
Erhaltene Danke: 20

Win 10
C# (VS 2012), C++ (VS 2012/GCC), PAWN(Notepad++), Java(NetBeans)
BeitragVerfasst: Fr 06.11.15 17:59 
user profile iconCsharp-programmierer hat folgendes geschrieben Zum zitierten Posting springen:
Warum sollte man kein try catch { } nehmen?

Das Problem hier liegt nicht am try/catch Konzept sondern am "catch { }"...Wenn eine Exception geworfen wird, dann passiert das nicht ohne Grund, und man sollte sie dementsprechend Abfangen und bearbeiten. Bei deine Variante wird der Fehler unter dem Teppich gekehrt. Im Moment scheint es ja den Teppich nicht zu stören, nur irgendwann ist kein Platz mehr darunter und du stehst vor einem Haufen unerklärlicher Fehler.
user profile iconCsharp-programmierer hat folgendes geschrieben Zum zitierten Posting springen:

Angenommen ich würde WorkingDirectory oder Application.StartupPath nehmen, welcher Pfad wäre das?
Und warum haut das im Debugger alles hin und ohne nicht?

Das WorkingDirectory ändert sich während der Laufzeit immer wieder. Das einfachste Beispiel ist die ein FileSave/OpenDialog. Der letzte Ordner der hier ausgewählt wurde ist dann das Working Directory.
Im Debugger ist sofern du es bei den Startoptionen nicht anders angegeben hast das gleiche wie Application.StartupPath
Application.StartupPAth ist der Pfad in der sich deine Exe befindet.
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Fr 06.11.15 18:47 
Wenn ich den Pfad der .exe nehme, erstellt das Programm den Ordner höchstwahrscheinlich auf dem Desktop, aber ich möchte den Ordner gern in Systemordner Eigene Datein haben. Ich habe jetzt ein kleines Testprogramm geschrieben, wo nun die Basis funktioniert:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
        string s = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            string y = Path.Combine(s, "Anwendung");
            if(!Directory.Exists(y))
            {
                Directory.CreateDirectory(y);
                Properties.Settings.Default.Pfad = y;
                Properties.Settings.Default.Save();
            }


Mir ist es jetzt nur ein Rätsel,warum im Debugger der komplette Pfad gespeichert wird und ohne den Debugger nur ein Teil davon. In meinem Textprogramm habe ich den selben Algorithmus angewendet wie in dem großem Programm. Hier wird der ganze Pfad auch ohne Debugger gespeichert. Kann es sein, dass es daran liegt, dass ich erst den Debugger verwedet habe und dann nicht mehr? Weil ich habe jetzt in dem Testprogramm den Debugger verwendet und nun wird auf einmal kein Pfad mehr angegeben. Wie soll ich in Zukunft meine Anwendungen ausführen? Mit Debugger oder ohne?
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 06.11.15 19:43 
Mit oder ohne Debugger hat damit nichts zu tun - du speicherst den Pfad ja nur, wenn das Verzeichnis noch nicht existiert ;-)
Warum speicherst du überhaupt den Pfad ab? Ermittle den Pfad doch einfach jedesmal bei Programmstart.
Csharp-programmierer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 696
Erhaltene Danke: 10

Windows 8.1
C# (VS 2013)
BeitragVerfasst: Fr 06.11.15 19:53 
Stimmt. Wo du recht hast, hast du recht. Dann werde ich die einzelnen Pfade der Ordner nun bei jedem Programmstart laden.
Muss ich bei dem Programmierern für Anwendungen, die auf anderen PC's laufen sonst noch irgendwas beachten?

PS: Ich bin fast vom Stuhl gefallen, wie viele Fehler beim Ausführern des Hauptprogramms aufgekommen sind. Gibt es da was besonderes zu beachten? Also ich z.B. eine neue Form öffnen wollte, überprüft das Programm ob eine Variable == null ist. Da kam ein Fehler. Den Algorithmus habe ich in einen try... catch { } Block gepackt und es lief. Da mir ein anderer User gesagt hat, dass man die Fehler nun unter den Teppich kehrt macht es keinen Sinn den Fehler zu verdecken. Soll ich es dann in Zukunkt so machen:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
try
{
 //Mach irgendwas...
}
catch(Exception ex)
{
 MessageBox.Show(ex.Message);
}
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 06.11.15 20:56 
Zitat:
Da mir ein anderer User gesagt hat, dass man die Fehler nun unter den Teppich kehrt macht es keinen Sinn den Fehler zu verdecken. Soll ich es dann in Zukunkt so machen:


Nein. Try..catch benutz man nur wenn man weiß wie man einen Fehler sinnvoll behandelt. Und einen Fehler behandeln heißt nicht es einfach dem User zu präsentieren und es zu seinem Problem zu machen. Was soll der denn machen wenn es ein Stackoverflow, OutOfMemory oder ein tatsächlicher Programmierfehler ist wie in deinem Eingangsbeispiel? Die Exception muss durchschlagen und es ist das Problem des Programmieres und nicht des Benutzers. Präsentiere Exception möglichst nur wenn sich daraus etwas ergibt worauf der User reagieren und es lösen kann, jenseits von "Befrage den Programmierer was er denn da für einen Müll produziert hat".

Und mach dir das Wort Exception nochmal bewusst. Es bedeutet "Ausnahme" und eben nicht "Üblicherweise".
Bezogen auf dein Eingangsproblem. Es ist normal das SelectedItems leer sein kann. Dieser Fall ist keine Ausnahme sondern ein Normalfall. Also prüft man das ab (z.B. mit einem if). Dann kann man auch was sinnvolles im Fall das das leer ist tun. Bei dir zum Beispiel die Textboxen leeren. Warum sollte da weiter die Daten der letzten Selektion drin stehen wenn jetzt nix mehr im ListView ausgewählt ist? Also weder Execptions schlucken noch einfach den User damit konfrontieren sondern das Exceptionauslösende Problem erkennen, verstehen und dann lösen. Sollte es ein Problem sein das ohne das Auftreten einer Exception nicht vernünftig lösbar ist dann auch nur genau diese Exception fangen und nicht jede und wenn möglich dann etwas sinnvolles tun und nicht den User damit belasten wenn der eh nix machen kann um das von sich aus zu lösen.

Zitat:
Wenn ich den Pfad der .exe nehme, erstellt das Programm den Ordner höchstwahrscheinlich auf dem Desktop,


Nur wenn die exe auf dem Desktop liegt.

Zitat:
Mit Debugger oder ohne?


Mit Debugger beim Programmieren. Testen natürlich ohne. Am Testen führt kein Weg vorbei. Und wenn man irgendwann mal in professionelle Richtungen denkt heißt testen auf jeder(!) Plattform die man unterstützt und garantiert nicht auf dem Rechner auf dem man auch programmiert hat. Entwicklungsrechner sind extrem schlechte Testrechner.