8

I built a script that mounts (attach) a VHD using Diskpart, cleans out some system files and then unmounts (detach) it. It uses a foreach loop and is suppose to clean multiple VHD using the same drive letter. However, after the 1st VHD it fails. I also noticed that when I try to manually attach a VHD with diskpart, diskpart succeeds, the Disk Manager shows the disk with the correct drive letter, but within the same PoSH instance I can not connect (set-location) to that drive. If I do a manual diskpart when I 1st open PoSH I can attach and detach all I want and I get the drive letter every time. Is there something I need to do to reset diskpart in the script? Here's a snippet of the script I'm using.

function Mount-VHD {
         [CmdletBinding()]
         param (
                 [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
                         [string]$Path,
                 [Parameter(Position=1,Mandatory=$false,ValueFromPipeline=$false)]
                         [string]$DL,
                 [string]$DiskpartScript = "$env:SystemDrive\DiskpartScript.txt",
                 [switch]$Rescan
         )

         begin {
                 function InvokeDiskpart {
                         Diskpart.exe /s $DiskpartScript
                 }
                 ## Validate Operating System Version ##
                 if (Get-WmiObject win32_OperatingSystem -Filter "Version < '6.1'") {throw "The script operation requires at least Windows 7 or Windows Server 2008 R2."}
         }
         process{
                 ## Diskpart Script Content ## Here-String statement purposefully not indented ##
 @"
 $(if ($Rescan) {'Rescan'})
 Select VDisk File="$Path" `nAttach VDisk
 Exit
 "@ | Out-File -FilePath $DiskpartScript -Encoding ASCII -Force
                 InvokeDiskpart
 Start-Sleep -Seconds 3
 @"
 Select VDisk File="$Path"`nSelect partition 1 `nAssign Letter="$DL"
 Exit
 "@ | Out-File -FilePath $DiskpartScript -Encoding ASCII -Force
                 InvokeDiskpart
                         }
         end {
                 Remove-Item -Path $DiskpartScript -Force ; ""
                 Write-Host "The VHD ""$Path"" has been successfully mounted." ; ""
         }
 }
 function Dismount-VHD {
         [CmdletBinding()]
         param (
                 [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$false)]
                         [string]$Path,
                 [switch]$Remove,
                 [switch]$NoConfirm,
                 [string]$DiskpartScript = "$env:SystemDrive\DiskpartScript.txt",
                 [switch]$Rescan
         )

         begin {
                 function InvokeDiskpart {
                         Diskpart.exe /s $DiskpartScript
                 }

                 function RemoveVHD {
                         switch ($NoConfirm) {
                                 $false {
                                         ## Prompt for confirmation to delete the VHD file ##
                                         "" ; Write-Warning "Are you sure you want to delete the file ""$Path""?"
                                         $Prompt = Read-Host "Type ""YES"" to continue or anything else to break"
                                         if ($Prompt -ceq 'YES') {
                                                 Remove-Item -Path $Path -Force
                                                 "" ; Write-Host "VHD ""$Path"" deleted!" ; ""
                                         } else {
                                                 "" ; Write-Host "Script terminated without deleting the VHD file." ; ""
                                         }
                                 }
                                 $true {
                                         ## Confirmation prompt suppressed ##
                                         Remove-Item -Path $Path -Force
                                         "" ; Write-Host "VHD ""$Path"" deleted!" ; ""
                                 }
                         }
                 }
                 ## Validate Operating System Version ##
                 if (Get-WmiObject win32_OperatingSystem -Filter "Version < '6.1'") {throw "The script operation requires at least Windows 7 or Windows Server 2008 R2."}
         }
         process{
         ## DiskPart Script Content ## Here-String statement purposefully not indented ##
 @"
 $(if ($Rescan) {'Rescan'})
 Select VDisk File="$Path"`nDetach VDisk
 Exit
 "@ | Out-File -FilePath $DiskpartScript -Encoding ASCII -Force
                 InvokeDiskpart
                 Start-Sleep -Seconds 10
         }
         end {
                 if ($Remove) {RemoveVHD}
                 Remove-Item -Path $DiskpartScript -Force ; ""
         }
 }
halr9000
  • 255
  • 2
  • 10
Kyle
  • 121
  • 4
  • Three days and still no answer. Anyone have any ideas? This is a creating a major delay in a project I have – Kyle Dec 14 '12 at 17:39
  • What OS are you running this script on? I ask mainly because 8/2012 have built-in VHD mount/unmounts cmdlets. You have a check to require 7/2008R2 but not a maximum. – MikeBaz - MSFT Dec 19 '12 at 14:59

2 Answers2

1

I can't see the exact point at which your script is failing, however the Set-Location test you mention reminds me of an issue I had in PoSH when trying to repeatedly map/un-map/map locations in a script.

https://stackoverflow.com/questions/10994979/net-use-only-works-once-in-powershell

In short use FILESYSTEM::X:\

instead of X:\

EDIT : Ok so I actually spent 30 seconds reading your script. I would put

$Path = FILESYSTEM::$Path

At the to of each function.

Patrick
  • 1,250
  • 1
  • 15
  • 35
0

I know this isn't directly an answer but have you tried not mounting it to a drive letter? Use the assign mount=<PATH> option instead and rig your cleaner script to work in that sub-directory.

Mark
  • 2,248
  • 12
  • 15