Autor Beitrag
MMali
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Di 07.07.15 08:39 
Guten Morgen allerseits.

Ich hab wieder eine Frage, hoffe sie passt hier ins .Net Forum.
Erstmal ein paar Daten dazu:
Ich benutze Visual Studios 2013 Express for Windows Desktop, Sprache C#.

Ich arbeite wieder an einem kleinen Programm mit dem ich USB-Sticks Bootfähig machen will.
Das funktioniert eigentlich soweit ganz gut indem ich mit new Process / Process.Start
eine batch aufrufe die Diskpart.exe startet, die Befehle für Diskpart.exe werden aus einer Textdatei ausgelesen.
Die Batch Variante ist ja oft verwendet soweit ich weis, ich weis natürlich das ich die batch weglassen kann und alles im Programm einarbeiten kann.

Aber mein Problem liegt eher darin das ich sobald ich mehrere USB-Sticks stecken hab und ich einen der nicht "Disk 1" ist dieser nicht bootfähig wird,
sondern nur die dazu benötigten files kopiert werden.
Wie kann ich diese Nummer auslesen? Ich hab in Google bis jetzt nichts gefunden.

Ich wähle den stick via FolderBrowserDialog, also der LW Buchstabe ist bekannt.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Di 07.07.15 11:16 
Du kannst alle Disks nacheinander auswählen und für jede Disk einzeln "DETAIL DISK" aufrufen.
Dann bekommst Du beispielsweise folgendes:

ausblenden Quelltext
1:
2:
3:
4:
5:
Volume ###  Bst  Bezeichnung  DS     Typ         Größe    Status     Info
----------  ---  -----------  -----  ----------  -------  ---------  --------
Volume 3         System-rese  NTFS   Partition    100 MB  Fehlerfre  System
Volume 4     C                NTFS   Partition    107 GB  Fehlerfre  Startpar
Volume 5     D                NTFS   Partition    125 GB  Fehlerfre

Mit Batch wirst Du da aber nicht weit kommen, außer Du willst tatsächlich die Tabelle in einem Batch-Script analysieren - dann wünsche ich dir viel Spaß :D
MMali Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Di 07.07.15 11:48 
Danke schon mal für deine Antwort.

Schon mal nicht schlecht so hab ich die Disk Nummer und den Pfad.
Aber wie werte ich die Tabelle/den Output am besten aus?
In eine Text Datei schreiben und dann Zeilenweise auslesen?
Oder wie würdest du Vorgehen?

Bis jetzt hab ich folgendes:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
static void bootable()
        {
            Process p = new Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
            p.StartInfo.RedirectStandardInput = true;
            p.Start();
 
            p.StandardInput.WriteLine("select disk 1");
            p.StandardInput.WriteLine("DETAIL DISK");
            p.StandardInput.WriteLine("exit");
            string output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            
            MessageBox.Show(output);
        }


PS: Ich werde wohl nicht bei Batch bleiben, so wurde es nur vorher gehandhabt.
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Di 07.07.15 17:32 
Du könntest dich eventuell danach richten, dass die Strichellinie zwischen Spalten-Header und Spalten-Body nie länger ist als der Inhalt. Du hast mit dem Anfangs-Index jeder Linie den Anfangsindex der Werte und mit der Länge der Linie auch die maximale Länge der Werte.

Ob das immer einheitlich bleibt, kann ich dir nicht sagen, das müsstest Du irgendwie testen.


Nach CSV kannst Du nicht gehen, da es kein einheitliches Trennzeichen gibt und teilweise Felder leer sind, weshalb Du nicht an Leerzeichen splitten kannst.
Eine Regexvariante fällt mir auch nicht ein, meine Ideen in der Richtung scheitern an der Tatsache, dass teilweise mehr als drei Leerzeichen zwischen zwei Spalten liegen oder einzelne Felder nur Leerzeichen enthalten.
MMali Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mi 08.07.15 08:28 
Also Zeilen/Spaltenweises auslesen?

Zeilen kann ich Problemlos auslesen, aber Spalten hab ich gerade keinen Ansatz.
Die Frage weicht vielleicht schon vom Thema ab aber hast du da für meinen Code evtl eine Erweiterung um eine Spalte auszulesen?
(Ich schreibe den Output in eine Text-Datei!)

ausblenden C#-Quelltext
1:
string LW = File.ReadLines(@"C:\test\bootable.txt").Skip(27).Take(1).First();					


So erhalte ich mal die richtige Zeile.
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: Mi 08.07.15 09:17 
Da die Ausgabe ein "fixed width"-Format darstellt, kannst du doch einfach mittels Substring(x, len) die entsprechenden Spaltenwerte auslesen.

Für diesen Beitrag haben gedankt: MMali
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Mi 08.07.15 12:28 
In der zweiten Zeile, die Trennlinien, die sind nie kürzer als die darunter liegenden Werte, höchstens Länger, aber das ist unwichtig.
Du kannst diese Trennlinien also als Grundlage verwenden, um die Breite der Spalten zu erfahren. Du splittest sie dafür an zwei Leerzeichen, vergiss diese Leerzeichen aber bei der nachfolgenden Berechnung nicht.
Außerdem kannst Du deren Startposition in der Zeile als Startposition jedes darunter liegenden Wertes verwenden.
Du musst dann ab dieser Stratposition die Länge der darüber liegenden Trennlinie weiter zählen. Der überschrittene Text ist dein Wert.

Ich würde daher eine Methode schreiben, die die Spalten-Infos aus liest. Der kennst Du ja direkt die zweite Zeile geben.
Als Ergebnis bekommst Du dann Index und Länge jeder Spalte und kannst damit dann in jeder anderen Zeile den Teil von index bis index + länge heraus schneiden.
Pro Wert dann noch über Trim() die Leerzeichen abschneiden und Du hast deine Werte.
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: Mi 08.07.15 13:25 
Palladin. der Aufwand lohnt wohl nicht - da reicht es einfach direkt den benötigten Spaltenwert einmalig zu ermitteln und als Konstante im Code zu verwenden. Die Ausgabe von "Diskpart" scheint ja konstant zu sein.
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: Mi 08.07.15 13:35 
Mit erscheint es viel zu kompliziert zu sein das per cmd/DiskPart zu machen. Entweder die Powershell automatisieren die hat an der Stelle (eigentlich an allen Stellen) tatsächlich mehr Power oder das Zeug direkt per WMI abfragen.

Beispiel.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
static void Main(string[] args)
{
    ManagementScope scope = new ManagementScope("\\\\.\\ROOT\\Microsoft\\Windows\\Storage");
    ObjectQuery query = new ObjectQuery("SELECT FriendlyName, Number FROM MSFT_Disk WHERE BusType = 7"); // 7 == USB
    using (var searcher = new ManagementObjectSearcher(scope, query))
    {
        foreach (ManagementObject mo in searcher.Get())
            Console.WriteLine(@"DiskName ""{0}"" - Number ""{1}""", mo["FriendlyName"], mo["Number"]);
    }
}


Für verfügbare Properties von MSFT_Disk guckst du msdn.microsoft.com/e...esktop/hh830493.aspx

Für diesen Beitrag haben gedankt: MMali
MMali Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mi 08.07.15 13:45 
Danke für eure Hilfe ich hab es mittlerweile so gelöst:
(Testversion, LWBuchstabe wird sonst mit Folderbrowserdialog zugewiesen)
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:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
        static string diskanzahl;
        static string LWBuchstabe = "E";

//Zum auslesen wieviele Disks am IPC stecken (Nicht mehr als 4 ohne C:\ möglich!)
        static void listdisk()
        {
            

            try
            {
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
                p.StartInfo.RedirectStandardInput = true;
                p.Start();
                p.StandardInput.WriteLine("list disk");
                p.StandardInput.WriteLine("exit");
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();

                using (StreamWriter sw = File.CreateText(@"C:\acronistools\test\bootable.txt"))
                {
                    sw.WriteLine(output);
                }
                using (StreamReader sr = File.OpenText(@"C:\acronistools\test\bootable.txt"))
                {
                    string inhalt = "";
                    inhalt = sr.ReadToEnd();
                    if (inhalt.Contains("Disk 1"))
                    {
                            diskanzahl = "1";

                        if (inhalt.Contains("Disk 2"))
                            diskanzahl = "2";

                        if (inhalt.Contains("Disk 3"))
                            diskanzahl = "3";


                        if (inhalt.Contains("Disk 4"))        
                            diskanzahl = "4";                       
                    }

                    else
                    {
                        MessageBox.Show(@"There is no Removable Drive!");
                    }
                } 
            } 
            catch (Exception ex)
            {
                MessageBox.Show("Attention: " + ex.Message, "© ... Austria GmbH");
            }
        }

// Funktion um LW Buchstaben zu erhalten:
        static void selectdisk1()
        {
            try
            {
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
                p.StartInfo.RedirectStandardInput = true;
                p.Start();
                p.StandardInput.WriteLine("select disk 1");
                p.StandardInput.WriteLine("DETAIL DISK");
                p.StandardInput.WriteLine("exit");
                string output = p.StandardOutput.ReadToEnd();
                p.WaitForExit();

                using (StreamWriter sw = File.CreateText(@"C:\acronistools\test\bootable.txt"))
                {
                    sw.WriteLine(output);
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show("Attention: " + ex.Message, "© ... Austria GmbH");
            }   
//Hier das auslesen des LW Buchstaben:

            string linesLW = File.ReadLines(@"C:\acronistools\test\bootable.txt").Skip(27).Take(1).First();
            string LW = linesLW.Substring(151);

// Vergleicht noch den ausgewählten LW Buchstaben mit dem ermittelten:
            if (LW == LWBuchstabe)
            {
//Schreibt in eine Textdatei für die Befehle der Batch
                 
                 List<string> lines = File.ReadAllLines(@"C:\make_stick_bootable\diskpart_cmd.txt").ToList<string>();
                 if (lines.Count >= 3)
                 {
                     lines.RemoveAt(3 - 1);
                     File.WriteAllLines(@"C:\make_stick_bootable\diskpart_cmd.txt", lines);
                     lines.Insert(3 - 1"select disk 1");
                     File.WriteAllLines(@"C:\make_stick_bootable\diskpart_cmd.txt", lines);
                 }

            }
        }
// Das ganze für jede Disk 
        static void selectdisk2()
   
        static void selectdisk3()
  
        static void selectdisk4()
    

// Zum ausführen der Funktionen:
        private void button1_Click(object sender, EventArgs e)
        {
            listdisk();
            if (diskanzahl == "1")
            {
                selectdisk1();
            }

            if (diskanzahl == "2")
            {
                selectdisk1();
                selectdisk2();
            }

            if (diskanzahl == "3")
            {
                selectdisk1();
                selectdisk2();
                selectdisk3();
            }

            if (diskanzahl == "4")
            {
                selectdisk1();
                selectdisk2();
                selectdisk3();
                selectdisk4();
            }           
        }
MMali Threadstarter
Hält's aus hier
Beiträge: 13



BeitragVerfasst: Mi 08.07.15 13:50 
@Ralf Jansen

Deine Version scheint mir doch um einiges kürzer zu sein.
Ich probier auch mal die Variante.
Danke dafür.

Aber so würde ich sagen meine Frage ist beantwortet.