Search code examples
c#cmddisk-partitioning

How to create simple volume from unallocated partition


I'm trying to open a place on my harddisk to store some licensing files.

So far I have tried diskpart. It looks easy to use but I could not format the unallocated partition with diskpart. I have found a way to create the unallocated space but I have to format it to use(correct me if I am wrong here. I'm really new on disk partition stuff)

This is my method to select the right volume. I've take it from here and it's working good. Link : C# and diskpart: how to select by disk label and not by a number? and the code I am using is this :

public int GetIndexOfDrive(string drive)
{
    drive = drive.Replace(":", "").Replace(@"\", "");

    // execute DiskPart programatically
    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();

    // extract information from output
    string table = output.Split(new string[] { "DISKPART>" },         StringSplitOptions.None)[1];
    var rows = table.Split(new string[] { "\n" }, StringSplitOptions.None);
    for (int i = 3; i < rows.Length; i++)
    {
        if (rows[i].Contains("Volume"))
        {
            int index = Int32.Parse(rows[i].Split(new string[] { " " }, StringSplitOptions.None)[3]);
            string label = rows[i].Split(new string[] { " " }, StringSplitOptions.None)[8];

            if (label.Equals(drive))
            {
                return index;
            }
        }
    }

    return -1;
}

once I get the index I run my own code to shrink that selected volume with this code :

Process DiskPartProc = new Process();                                  
DiskPartProc.StartInfo.CreateNoWindow = true;
DiskPartProc.StartInfo.UseShellExecute = false;                        
DiskPartProc.StartInfo.RedirectStandardOutput = true;                  
DiskPartProc.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe"; 
DiskPartProc.StartInfo.RedirectStandardInput = true;                   
DiskPartProc.Start();
DiskPartProc.StandardInput.WriteLine("select volume "+index);
DiskPartProc.StandardInput.WriteLine("shrink desired=16 minimum=16");
DiskPartProc.StandardInput.WriteLine("exit");                          
string output = DiskPartProc.StandardOutput.ReadToEnd();               
DiskPartProc.WaitForExit();

Once I do this the result is like this :

http://prntscr.com/mjwg0t (Picture of an unallocated partition only)

I can right click on it and create new simple volume from that unallocated partition but I have to do this with diskpart commands. Can someone tell me which diskpart commands do I have to use to achieve this? And how can I get detailed information about this volume?


Solution

  • I have solve my problem. This is my final code:

    int index = GetIndexOfDrive(Path.GetPathRoot(@"E:\"));
    
    Process DiskPartProc = new Process();
    DiskPartProc.StartInfo.CreateNoWindow = true;
    DiskPartProc.StartInfo.UseShellExecute = false;
    DiskPartProc.StartInfo.RedirectStandardOutput = true;
    DiskPartProc.StartInfo.FileName = @"C:\Windows\System32\diskpart.exe";
    DiskPartProc.StartInfo.RedirectStandardInput = true;
    DiskPartProc.Start();
    DiskPartProc.StandardInput.WriteLine("select volume " + index);
    DiskPartProc.StandardInput.WriteLine("shrink desired=16 minimum=16");
    DiskPartProc.StandardInput.WriteLine("create partition primary size=16");
    DiskPartProc.StandardInput.WriteLine("format fs=ntfs label=\"MyPlace\" quick");
    DiskPartProc.StandardInput.WriteLine("exit");
    string output = DiskPartProc.StandardOutput.ReadToEnd();
    DiskPartProc.WaitForExit();
    

    The problem was something about my own disk. I have put another spare one and did all my test on it and it work perfectly, now I can create a disk volume inside a disk and format it and then I can access it with its volume ID. I still have to find a way to do it in C#. I can do the last part from windows not from C# yet. I need a way to access that volume now. I tried Directory.Exist but it did not worked out.

    EDIT : I found a way to check. Since I put only 1 file and nothing else in my volume I use this code :

    Process MountProc = new Process();
                MountProc.StartInfo.CreateNoWindow = true;
                MountProc.StartInfo.UseShellExecute = false;
                MountProc.StartInfo.RedirectStandardOutput = true;
                MountProc.StartInfo.FileName = "mountvol";
                MountProc.StartInfo.RedirectStandardInput = true;
                MountProc.Start();
                MountProc.StandardInput.WriteLine("mountvol");
                MountProc.StandardInput.WriteLine("exit");
                string MountOutput = MountProc.StandardOutput.ReadToEnd();
                MountProc.WaitForExit();
    
                string VolumeGUID = string.Empty;
                List<string> VolList = MountOutput.Split(new string[] { "Possible values for VolumeName along with current mount points are:" }, StringSplitOptions.None)[1].Split('\n').Where(x => x != "\r").Where(x => x != "").ToList();
                List<string> ClearList = VolList.Select(s => s.Trim().Replace("\r", "")).ToList();
                for (int i = 0; i < ClearList.Count; i++)
                {
                    if (ClearList[i].StartsWith(@"\\?\Volume") && ClearList[i + 1].StartsWith("***")) 
                    {
                        string tmpPath = ClearList[i].Replace(@"\\?\", @"\\.\");
                        if (Directory.Exists(tmpPath))
                        {
                            string[] DirectoryList = Directory.GetDirectories(tmpPath, "*.*", SearchOption.TopDirectoryOnly);
                            string[] FileList = Directory.GetFiles(tmpPath, "*.*", SearchOption.TopDirectoryOnly);
    
                            if(DirectoryList.Length==0 && FileList.Length==1)
                            {
                                if (Path.GetExtension(FileList[0]) == ".license") 
                                {
                                    Console.WriteLine("\n\n\n\t\rLicense file found in : " + FileList[0]);
                                    File.Copy(FileList[0], "LIC.license", true);
                                    Console.WriteLine("\n\t\rContent of license file : " + File.ReadAllText("LIC.license"));
                                    File.Delete("LIC.license");
                                }
                            }
                        }
                    }
                }
                Console.ReadKey();
    

    The reason why I copied the file to another location and open it there is I can't open it with File class if it's accessed with it's ID(e.g. \.\Volume{UNIQUE_ID}\)