0

I need to develope an application (Windows Forms) which facilitate the user the action of change a disk letter. I know how to do it from cmd:

  • diskpart
  • List volume
  • Select volume X
  • Assign letter = K

The interface for my app is supposed to be something like this: Appearence of interface

I know how to execute these commands from c#, but I would like to show the result of "List volume" command in my list box in order the user can select the volume they wanted to change the letter and press the button "CHANGE LETTER".

My question is how to do the first task, I mean, show the result of List volume in the list box.

Here is my code since now:

        Process p = new Process();
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
        p.StartInfo.RedirectStandardInput = true;
        p.Start();
        p.StandardInput.WriteLine("list volume");

        string output = p.StandardOutput.ReadToEnd();

I can't see the value of output when I run the program. Thank you for your help!

Neus
  • 17
  • 5
  • I guess you have some code showing how you put output into your listbox? What have you tried so far to do that? – Mike May 31 '18 at 07:30
  • Hi, this is what I do not know how to do it.What I have tried is to save the output in a file and then read it to add to the list box but failed. – Neus May 31 '18 at 07:33
  • It seems like you want to convert your string output to a `list`. I Guess there is some way for you to `Split()` the output. – Mike May 31 '18 at 07:36
  • @Mike I think he is not getting any output from the code he is running. – Gaurang Dave May 31 '18 at 07:39
  • Yes Mike, that would be perfect. My problem is that I don't know how to do it. If I execute: string output = p.StandardOutput.ToString() output has the value "System.IO.StreamReader" and if I run string output2 = p.StandardOutput.ReadToEnd(); I don't get any value for output2. The program seems to do nothing – Neus May 31 '18 at 07:44
  • Perhaps this is a better way for you to get the drive letters? [How to get Drive Letter and Name (volume label)](https://stackoverflow.com/questions/19185655/how-to-get-drive-letter-and-name-volume-label) – Mike May 31 '18 at 07:45
  • Yes, I saw that question... the problem is that I can get the volume letter but not change them with SSD drives (with USB drives worked). And the system needs to have a drive called K all the time (and users don't want to use windows tools to work with) – Neus May 31 '18 at 07:48
  • I think you need to send `"list volume\r\nexit\r\n"` so that the process will exit. Otherwise `ReadToEnd()` will block forever. – John Wu May 31 '18 at 07:51
  • I'm going to try to explain myself better. I have a system whic saves data in a SSD disk and this disk needs to be replaced daily. So the new SSD disk they insert, needs to have the same letter in order to another application can keep saving data in the same path. Users can do it with Windows tools, using diskpart... but they wan't an specific tool developed to this purpose. My idea was an interface like I attached to facilitate this work. Just show the volumes detected, and change the letter of the volume selected in the list box – Neus May 31 '18 at 07:53
  • I think I made a progress with John Wu explanation! Using "list volume\n\nexit\r\n" and output2 = p.StandardOutput.ReadToEnd(), output2 have volumes information. Thank you all for your time, let me try to solve some things and I let you know how the final code is. – Neus May 31 '18 at 08:02

2 Answers2

0

Following code will return you list of drives. Your question is little bit of lengthy but you need to perform all the string parsing ahead to get list of drives from this string.

Process process = new Process();
process.StartInfo.FileName = "diskpart.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.StandardInput.WriteLine("list volume");
process.StandardInput.WriteLine("exit");
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();


var op = output.Split(new string[] { "DISKPART>" }, 3, StringSplitOptions.RemoveEmptyEntries)[1].Split(new string[] { Environment.NewLine },10, StringSplitOptions.RemoveEmptyEntries);
Gaurang Dave
  • 3,956
  • 2
  • 15
  • 34
0

you can use DriveInfo to more easily get the current driveletters then adding the drives to the listBox is simple:

drives = DriveInfo.GetDrives().ToList();
//Don't know the name of your listBox.
listBox.ItemsSource = drives;

After that you press the Button where you want to change the driverinfo. I don't know if you need the driveletter or the index of the driveletter so this code gives you both.

private static void Btn_Click(object sender, System.Windows.RoutedEventArgs e)
{
    string driveLetter = (string)listBox.SelectedItem;
    int index = drives.FindIndex(x => x.Name == driveLetter);

    //Perform the work of changing the driveletter using index or driveletter

    drives = DriveInfo.GetDrives().ToList();
    listBox.ItemsSource = drives;
}

I assume you already know how to do the work of changing the driveletter.

Mike
  • 850
  • 10
  • 33
  • Hi Mike! I think I know how to do it, Now I'm trying :) I let you know my final code. Thank you! – Neus May 31 '18 at 08:45