Entwickler-Ecke

WinForms - Ordner erstellen lassen


tomo2403 - Fr 10.08.18 18:57
Titel: Ordner erstellen lassen
Hey Leute, :wave:

hab mal ne Frage. Ich weiß wie man in einer WinForm daten speichern und laden kann.
Kann mir aber bitte mal jemand sagen wie man Ordner erstellt? :gruebel:

So speichere und lade ich:


Klasse
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:
using System;
using System.Runtime.Serialization.Formatters.Binary;

namespace App
{
    [Serializable]
    public class AppData
    {
        public string data { get; set; }

        public void save(string path)
        {
            System.IO.FileStream FS = new System.IO.FileStream(path, System.IO.FileShare.Create);
            BinaryFormatter BF = new BinaryFormatter();


            BF.Serialize(FS, this);
            FS.Dispose();

        }

        public AppData load(string path)
        {
            AppData AD = new AppData();

            System.IO.FileStream FS = new System.IO.FileStream(path, System.IO.FileMode.Open);
            BinaryFormatter BF = new BinaryFormatter();

            AD = (AppData)BF.Deserialize(FS);

            FS.Dispose();
            return AD;
        }
    }
}


Laden
1:
2:
3:
AppData ADl = new AppData();
ADl = ADl.load(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Datei.dll");
variable= ADl.data;


Speichern
1:
2:
3:
AppData ADs = new AppData();
ADs.data = "";
ADs.save(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Datei.dll");


Moderiert von user profile iconTh69: Titel geändert ("stellen" -> "erstellen").


Ralf Jansen - Fr 10.08.18 19:16

Ruf einfach

C#-Quelltext
1:
Directory.CreateDirectory(path);                    

auf.
CreateDirectory erzeugt alle fehlende Ordner die im Pfad stecken. Wenn in "c:/Dir1/Dir2/Dir3" der Ordner dir1 schon existiert werden nur die Unterordner 2 und 3 erstellt.
Heißt dort wo du den Ordner brauchst musst du nicht testen ob der Ordner schon existiert du kannst einfach immer CreateDirectory aufrufen. Im Zweifel wenn der Ordner schon existiert macht die Methode halt einfach nix.

Da du das vermutlich in AppData.save brauchst rufe da am Anfang einmal

C#-Quelltext
1:
Directory.CreateDirectory(Path.GetDirectoryName(path));                    

aus. Da bei dir scheinbar der path nicht der Ordnername sondern der Filename ist mußt du aus dem Filename per Path.GetDirectoryName den Ordnernamen extrahieren.


tomo2403 - Fr 10.08.18 20:05

Wenn ich aber

C#-Quelltext
1:
Directory.CreateDirectory(Path.GetDirectoryName(Environment.SpecialFolder.ProgramFiles.ToString()) + "\\dir1\\dir2");                    

oder

C#-Quelltext
1:
Directory.CreateDirectory((Environment.SpecialFolder.ProgramFiles.ToString()) + "\\dir1\\dir2");                    

anwende, passiert nichts.

Immer wenn ich auf Systemordner zugreifen möchte wir dies verweigert!


Ralf Jansen - Fr 10.08.18 20:24

In ProgramFiles hat ein normaler User auch keine Rechte. Da gehören nur Programdateien hin die von z.B. einem Installer dahingeschoben werden.
Wenn du irgendwas zur Laufzeit irgendwo ablegen musst dann gehört das eher in einen der ApplicationData Ordner. Du nennst deine Klasse ja auch schon AppData ;)
Welchen ApplicationData Ordner genau hängt dann davon ab was du willst. Per User, für alle User gleich, soll das mit dem Profil auf andere Rechner roamen etc.


Wenn du trotzdem aus irgendeinem Grund, gegen die Best Practices von Windows, doch da was hioschreiben willst muss du dir für dein Programm oder zumindest diesen Codeteil erhöhte Rechte anfordern. Stichwort User Access Control (UAC).


tomo2403 - Fr 10.08.18 20:37

ApplicationData funktioniert auch nicht und mit UAC komme ich nicht klar. :(


Ralf Jansen - Fr 10.08.18 20:45

Dann sollten wir uns mal fragen wie du das ausprobierst. Wenn das ein Rechteproblem ist oder sonst aus irgend einem Grund der Ordner nicht angelegt werden konnte bekommst du eine Exception und die sollte dir sagen was das Problem ist. Mindestens beim debuggen sollte du die prominent zu sehen bekommen.


tomo2403 - Fr 10.08.18 20:52

Fehler im Bild

(Statt Desktop steht da eigentlich AppData in der Fehlermeldung)


Ralf Jansen - Fr 10.08.18 21:16

Ich vermisse in der Methode irgendwie den besprochenen Aufruf von Directory.CreateDirectory :gruebel:


tomo2403 - Sa 11.08.18 16:33

Es geht immer noch nicht! Kannst du mir bitte ein Codebeispiel erstellen? Ich bin einfach zu blöd. :?

Außerdem wir die Methode ... nicht aufgerufen!

C#-Quelltext
1:
2:
Directory.CreateDirectory((Environment.SpecialFolder.ApplicationData.ToString() + "\\T-App Germany\\Knuffi, der programmierbare Hund\\"));
Directory.CreateDirectory(Path.GetDirectoryName(Environment.SpecialFolder.ApplicationData.ToString() + "\\T-App Germany\\Knuffi, der programmierbare Hund\\"));


Könnte es vielleicht daran liegen, dass der Ordner AppData versteckt ist?


Ralf Jansen - Sa 11.08.18 18:02


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
public void save(string path)
{
    Directory.CreateDirectory(Path.GetDirectoryName(path)); // <- einfach einfügen
    System.IO.FileStream FS = new System.IO.FileStream(path, System.IO.FileShare.Create);
    BinaryFormatter BF = new BinaryFormatter();

    BF.Serialize(FS, this);
    FS.Dispose();
}



Zitat:
Könnte es vielleicht daran liegen, dass der Ordner AppData versteckt ist?


Nein, versteckt heißt einfach nur da du den in verschiedenen Tools wie zum Beispiel den Explorer nicht einfach so siehst. Ändert aber nichts an Rechten.


Delete - Sa 11.08.18 18:11

- Nachträglich durch die Entwickler-Ecke gelöscht -


tomo2403 - So 12.08.18 12:18

Ich habe das ganze jetzt einfach so gelöst:

Ausschnitt aus Serializable Class
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
        string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "\\T-App Germany\\Knuffi, der programmierbare Hund");

        public void Save(string path)
        {

            Directory.CreateDirectory(folder);
            Directory.CreateDirectory(Path.GetDirectoryName(folder));

            FileStream FS = new FileStream(path, FileMode.Create);
            BinaryFormatter BF = new BinaryFormatter();


            BF.Serialize(FS, this);
            FS.Dispose();
        }


Danke! :) :wink:


Th69 - So 12.08.18 13:03

Aber warum 2x CreateDirectory?
Und warum benutzt du nicht den übergebenen Pfad path (so wie Ralf es ja schon geschrieben hat)?

Ich habe den Eindruck, da fehlt ein bißchen das Verständnis für den Code - und "Trial and Error" führt selten zum Erfolg.


tomo2403 - So 12.08.18 13:41

Zitat:
Und warum benutzt du nicht den übergebenen Pfad path (so wie Ralf es ja schon geschrieben hat)?

Weil der Code nicht Funktioniert!
Wenn ich das ausführe, kommt wieder der Fehler mit der Zugriffsberechtigung!


Th69 - So 12.08.18 13:52

Welchen Pfad übergibst du denn?


tomo2403 - So 12.08.18 13:56


C#-Quelltext
1:
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "\\T-App Germany\\Knuffi, der programmierbare Hund"                    

Das Problem ist das VS nur den Pfad \\T-App Germany\\Knuffi, der programmierbare Hund übergiebt.
ProgramFiles wir nicht mit eingebunden.


Th69 - So 12.08.18 14:17

Auch das hat Ralf doch schon geschrieben, daß du im ProgramFiles-Ordner (und deren Unterordner) keine Schreibrechte hast (nur System, Admin, Installer, etc.).
Und da dies der selbe Pfad wie dein string folder ist, kann auch der vorherige Code nicht damit funktionieren.


tomo2403 - So 12.08.18 14:19

Bei AppData funktioniert es auch nicht!
Er versucht außerdem das ganze unter D:\ zu speichern. (es soll aber C:\)


Th69 - So 12.08.18 14:19

Wie sieht dein kompletter Aufruf der Save-Methode aus?

Btw: Eigenschaften- und Methodennamen sollten mit einem Großbuchstaben beginnen (um sie von privaten Membern zu unterscheiden)


tomo2403 - So 12.08.18 14:25


Klasse
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:
    [Serializable]
    public class AppData
    {
        public string AdminToolData { get; set; }

        string folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "\\T-App Germany\\Knuffi, der programmierbare Hund");

        public void Save(string path)
        {
            Directory.CreateDirectory(folder);
            Directory.CreateDirectory(Path.GetDirectoryName(folder));

            FileStream FS = new FileStream(path, FileMode.Create);
            BinaryFormatter BF = new BinaryFormatter();


            BF.Serialize(FS, this);
            FS.Dispose();
        }

        public AppData Load(string path)
        {
            AppData AD = new AppData();

            FileStream FS = new FileStream(path, FileMode.Open);
            BinaryFormatter BF = new BinaryFormatter();

            AD = (AppData)BF.Deserialize(FS);

            FS.Dispose();
            return AD;
        }
    }



Speichern/Laden
1:
2:
3:
4:
5:
6:
                AppData ADs = new AppData();
                ADs.AdminToolData = (string)"hier steht text";
                ADs.Save(folder + "\\AppData.dll");

                AppData ADl = new AppData();
                ADl = ADl.Load(folder + "\\AppData.dll");


Th69 - So 12.08.18 20:19

So, da bin ich wieder - ich hatte das schöne Wetter für einen Ausflug genutzt. ;-)

user profile icontomo2403 hat folgendes geschrieben Zum zitierten Posting springen:
Bei AppData funktioniert es auch nicht!
Er versucht außerdem das ganze unter D:\ zu speichern. (es soll aber C:\)


Was gibt denn Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) zurück? Hast du deine System-Verzeichnisse auf mehrere Partitionen verteilt? Oder hat der aktuelle Benutzer nur spezielle Rechte?

Es gibt ja auch noch SpecialFolder.CommonApplicationData sowie SpecialFolder.LocalApplicationData, s. Environment.SpecialFolder-Enumeration [https://msdn.microsoft.com/de-de/library/system.environment.specialfolder(v=vs.110).aspx].

Trotzdem solltest du den Code von Ralf verwenden:

C#-Quelltext
1:
2:
3:
4:
5:
public void Save(string path)
{
    Directory.CreateDirectory(Path.GetDirectoryName(path));
    // ...
}
(denn wenn du diese Methode mit einem anderen Pfad als folder aufrufst, dann würden ja nicht die passenden Unterverzeichnisse angelegt)
Und das Rechteproblem solltest du getrennt davon angehen (also z.B. kannst du als Benutzer über den Explorer in diesem Verzeichnis Unterverzeichnisse erstellen?).

PS: Warum speicherst du die serialisierten Daten unter ".dll" ab? ".config" oder ".txt" o.ä. wäre wohl passender.
Und zum Zusammensetzen von Pfaden solltest du generell Path.Combine verwenden (nicht "\\...")!


tomo2403 - Di 14.08.18 15:05

Ich werde Wahnsinnig! Jetzt hat er auch auf D:\ keine Rechte mehr!

Mein System lieg allein auf C:\ und der Benutzer ist Administartor. An den rechten habe ich nichts verändert.

Bei SpecialFolder.CommonApplicationData und SpecialFolder.LocalApplicationData funktioniert es auch nicht.
Der Code von Ralf hat auch nichts gebracht.

Warum .dll? Weil die wenigsten darauf kommen diese Datei im txt-Editor zu öffnen um die Werte zu verändern.
.config ist auserdem eine Datei die von VS erstellt wird. Ich möchte nicht, dass mein Projekt nochmal kaputt geht. (diesen Fall hatte ich schonmal (lange Geschichte)).

Mal so neben bei: Thema ansehen [https://www.entwickler-ecke.de/viewtopic.php?p=712976#712976]


Christian S. - Di 14.08.18 18:39

user profile icontomo2403 hat folgendes geschrieben Zum zitierten Posting springen:
Mal so neben bei: Wie kann ich eine Konsole über eine WinForm starten lassen das diese Angezeigt wird? (WinForm(ein Projekt) + ConsolenApp(ein Projekt) (= beides in einer Peojektmappe))
Erstelle für eine neue Frage bitte auch einen neuen Thread im Forum, damit das hier nicht durcheinander geht. Danke! :)


Delete - Mi 15.08.18 13:33

- Nachträglich durch die Entwickler-Ecke gelöscht -


tomo2403 - Mi 15.08.18 15:24

Nicht ganz!

Path.Combine kann nur zwei strings kombinieren.

C#-Quelltext
1:
2:
3:
4:
5:
// geht nicht!
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "T-App Germany""Knuffi, der programmierbare Hund");

// geht!
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "T-App Germany\\Knuffi, der programmierbare Hund");


Das speichern funktioniert ... aber das laden nicht! (siehe Bild)

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
                AppData appData = new AppData();
                try
                {
                    appData.AdminToolData = "Some text";
                    appData.Save("SomeFile.txt");
                }
                finally
                {
                    appData = null;
                }

                try
                {
                    appData.Load("SomeFile.txt");
                    MessageBox.Show(appData.AdminToolData);
                }
                finally
                {
                    appData = null;
                }


Delete - Mi 15.08.18 15:39

- Nachträglich durch die Entwickler-Ecke gelöscht -


tomo2403 - Mi 15.08.18 15:52

Ach ich Vollidiod! Ich habe alles kopiert und diese eine Zeile gelöscht weil das Program gesagt hat das appData schon vorhanden ist. Das ich den Namen ändern muss habe ich überhauptnicht gemerkt :!:

Das mit Path.Combine funktioniert aber zumindest nicht so, wie du es hingeschrieben hast!

Aber trozdem ein Danke an alle!


Delete - Mi 15.08.18 15:58

- Nachträglich durch die Entwickler-Ecke gelöscht -


Ralf Jansen - Mi 15.08.18 16:28

Zitat:
Path.Combine() scheint scheinbar nur bei dir ein Problem darzustellen.


Jeder der gegen ein Framework arbeitet kleiner als Net 4 hätte dieses Problem ;) Die entsprechenden Überladungen gibt es erst seit dem.


tomo2403 - Do 16.08.18 16:02

Da liegt das Problem! Mein Projekt ist in 3.0 :idea:


Th69 - Do 16.08.18 19:23

Dann führe die Methoden nacheinander aus (mit jeweils 2 Parametern) oder wechsle auf .NET 4.0 (oder höher).