VDS Under PowerShell

OK so if you read my last Blog, you know I was busy playing around with VDS under C#

I has hit a sticking point in that code where I couldn’t set the disk offset or alignment as

I needed to call the AdvancedDisk’s BeginCreatePartitionMbr and I just couldn’t seem to get away from viewing everything as a volume!!

So unless someone posts to my blog about how to set Disk Offsets and Alignments I thought lets use DiskPart to do the work, and then I thought why not try PowerShell as I always ment to write some stuff in that…

So here we go a full disk import/partition/drive letter assignment all in PowerShell using a lot from the C# blog, please read it first and read the links too..

I take no responsibility if you completely destroy your disks and data by using this information

As always if you don’t understand what is going on then DON’T DO IT!!
Anyway now that is out of the way, here is the script I worked out..

# Start a capture of what is going on!!!
    Start-Transcript -Path “c:\Disks.log” –Append

# Set up VDS here!!
    $VdsServiceLoader = $null
    $VdsService = $null

# Load the VDS Service
    [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.Storage.Vds”) | Out-Null
    $VdsServiceLoader = New-Object Microsoft.Storage.Vds.ServiceLoader
    $VdsService = $VdsServiceLoader.LoadService($null)
    $VdsService.WaitForServiceReady() 

# Scan for New Drives
    $vdsService.Reenumerate()

# Refresh Cache
    $vdsService.Refresh()   

# Find the Basic Disk Provider
    $vdsBasicProvidorGuid = “ca7de14f-5bc8-48fd-93de-a19527b0459e”
    $VdsService.HardwareProvider = $false
    $VdsService.SoftwareProvider = $true
    Write-Host ” “
    Write-Host “Looking for the VDS Software Proivder…”
    foreach($SoftwareProvider in $VdsService.Providers)
    {
    if ($vdsBasicProvidorGuid -eq $SoftwareProvider.Id )
        {
            Write-Host ”  Found the”  $SoftwareProvider.Name
            $basicProvider = $SoftwareProvider
        }
    }

# Load into a disk pack any unallocated disks   
    Write-Host ” “
    Write-Host “Loading Unallocated Disks”
    foreach($unallocatedDisk in  $VdsService.UnallocatedDisks)
    {
        $vdsDiskPack = $basicProvider.CreatePack()
        $vdsDiskPack.AddDisk($unallocatedDisk.Id, [Microsoft.Storage.Vds.PartitionStyle]::Mbr,$false)
    }

# Bring On-line any offline disks and make R/W
    Write-Host ” ”
    Write-Host “Bringing All Connected Disks On-Line”
    foreach ($DiskPack in  $basicProvider.packs)
    {
         foreach ($packDisk in $diskPack.Disks)
         {
             Write-Host $packdisk.id $packdisk.status
             if ($packDisk.Status -eq [Microsoft.Storage.Vds.DiskStatus]::Offline)
                {    
                   Write-Host “Disk is Offline.. Brining OnLine Now”                  
                   $packDisk.Online() # Bring disk online..
                   $packDisk.ClearFlags([Microsoft.Storage.Vds.DiskFlags]::ReadOnly) # Ensure that disk is R/W
                   $packDisk.Refresh()            
                }
          }
      }

# Now find all disks with 0 partitions and partition them to the whole disk
# Note we can add the offset\alignment in here – create part pri offset=x  align=y..
# See http://support.microsoft.com/kb/929491
    Write-Host ” ”
    Write-Host “Checking for disks with no partitions and Partitioning..”
    $disksToPartition = Get-WmiObject -ComputerName “localhost” -query “SELECT * FROM Win32_DiskDrive Where partitions=0”
    foreach ($disk in $disksToPartition)
    {
        if($disk.index -ne $null) # Ensure we have a disk!!
            {
                    Write-Host “We need to partition disk ” $disk.index
                    $target=$disk.index
                    @(“select disk $target”,”Create Part Pri align=1024″) | diskpart
            }   
        else
            {
                Write-Host ” No unpartition disks found..”
            }
    }
       Write-Host ”  All Disks Have Valid Partitions”

# Now remove ALL drive letters (Except C:)
    Write-Host ” ”
    Write-Host “Clearing All drive letters…”
    $Volumes = Get-WmiObject -computerName “localhost” -query “SELECT * FROM Win32_Volume WHERE DriveLetter <> ‘C:'”

    foreach ($volume in $Volumes)
    {    
        $volname = $volume.DriveLetter
        if ($volname -ne $null)
        {
            Write-Host ”  Found Existing Drive Letter” $volume.DriveLetter
            Write-Host ”    Removing Letters from Volume” $volname
            @(“select volume $volName”,”remove all” ,”exit” ) | diskpart
        }
    }

# Now find CD Drives and allocate Letters..
    Write-Host ” ” | Out-File $logfile -append
    Write-Host “Allocating Drive Letters”
    $CDDrives = Get-WmiObject -computerName “localhost” -query “Select * from Win32_CDROMDrive”

# Create an array of possible drive letters
    $DriveLetterArray=”GILMNOPQRSTUV” # These are for Disk Drives avoiding drives I wish to keep for Net Use etc
    $i=0
    $CDDriveArray=”ZYX” # These are for CD Drives
    $j=0
    foreach ($DiskPack in  $basicProvider.packs)
    {
        foreach ($vdsVolume in $DiskPack.volumes)
        {

           # Note the updated logic to spotting a CD drive here!! Now we look for the file system types it can support
            if ($vdsVolume.RecommendedFileSystemType -ne [Microsoft.Storage.Vds.FileSystemType]::Ntfs)
            {
                Write-Host ”  Found Possible CD Drive” $vdsVolume.name ” Setting Drive Letter to ” $CDDriveArray[$j]
                Write-Host ”   Recommended File System is” $vdsVolume.RecommendedFileSystemType
                $vdsVolume.DriveLetter = [Char]::Parse($CDDriveArray[$j]) # Pick unused Drive Letter
                $j=$j+1
            }
            else
            {
            if($vdsVolume.DriveLetter -ne “C”) # Don’t touch the C Drive!!
                {
                Write-Host ”  Writing Letter ” $DriveLetterArray[$i] “to ” $vdsVolume.name 
                 Write-Host ”   Recommended File System is” $vdsVolume.RecommendedFileSystemType
                $vdsVolume.DriveLetter = [Char]::Parse($DriveLetterArray[$i]) 
                $i=$i+1
                }
            }
        }
    }

# Note show enum (This is just showing off the possible value it could be using fancy call I found somewhere)
    $enums=[enum]::GetValues([Microsoft.Storage.Vds.VolumeFlags])
    “Microsoft.Storage.Vds.VolumeFlags enum has {0} possible values” -f $enums.count | Out-File $logfile -Append
    $i=1
    $enums|%{“Value {0}: {1}” -f $i,$_.tostring();$i++} | Out-File $logfile -Append
    “”

# Now to format the Drives…
    Write-Host ” “
    Write-Host “Formatting Unformatted Drives”
    # See http://msdn.microsoft.com/en-us/library/aa394515(VS.85).aspx for details (DriveType=3 means Local Disk)
    $unformatedDrives = Get-WmiObject -computerName “localhost” -query “select * from win32_volume where filesystem=null and drivetype=3”
    foreach ($unformatedDrive in $unformatedDrives)
    {
        if($unformatedDrive -ne $null) # Ensure we have something to format
        {
            Write-Host ” Formatting Drive” $unformatedDrive.Name
            $unformatedDrive.format(“NTFS”,$true,512,”Data”,$false) | Out-File $logfile -append
        }
    }

# Now write the settings out to confirm it all worked..

# See http://support.microsoft.com/kb/929491 about partitioning
# Confirms details set..
    Write-Host ” “
    Write-Host “Outputting Disk Offsets”
    Get-WmiObject -ComputerName “localhost” -Class “Win32_DiskPartition” |
    ft SystemName, Name, DiskIndex, Size, StartingOffset, BlockSize  -AutoSize

# Show Logical partitions to Logical Disk Drive
# http://chadwickmiller.spaces.live.com/blog/cns!EA42395138308430!291.entry
    Write-Host ” “
    Write-Host “Outputing Disk to Logical Partition Details..”
    $partitions = Get-WmiObject -computerName “localhost” Win32_DiskPartition

    $partitions | foreach { Get-WmiObject -computerName “localhost” -query “ASSOCIATORS OF {Win32_DiskPartition.DeviceID=’$($_.DeviceID)’} WHERE AssocClass = Win32_LogicalDiskToPartition” |
                add-member -membertype noteproperty PartitionName $_.Name -passthru |
                add-member -membertype noteproperty Block $_.BlockSize -passthru |
                add-member -membertype noteproperty StartingOffset $_.StartingOffset -passthru |
                add-member -membertype noteproperty StartSector $($_.StartingOffset/$_.BlockSize) -passthru } |
                Select SystemName, Name, PartitionName, Block, StartingOffset, StartSector | ft | Out-Host
 
Stop-Transcript

Advertisements
This entry was posted in Computing and tagged . Bookmark the permalink.

1 Response to VDS Under PowerShell

  1. Pingback: Diskpart.exe durch Powershell ersetzen mittels Virtual Disk Service « Das nie endende Chaos!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s