Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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, within that instance, I can attach and detach all I want and I get the drive letter every time, but the minute I run the script the a drive letter gets destroyed within the instance after use. Is there something I need to do to reset diskpart in the script? Here's a snippet of the script I'm using.

$test=""
    $Test2=""
    $MsgBoxObj = New-Object -ComObject wscript.shell
    $all = @()
    $obj = New-Object System.Collections.ArrayList 
    $hash = @{}
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
        [gc]::collect()
        Start-Sleep -Seconds 15
        reg unload hklm\DesktopVM 
        reg unload hklm\DesktopSoft

    }
    end {
        if ($Remove) {RemoveVHD}
        Remove-Item -Path $DiskpartScript -Force ; ""
        }

}
Function mount-it {param($source, $privatename)
#Import-Module "F:\Scripts\LJ_Cleanup\mount.psm1"
# Script to use a mounted VHD to clean off the LJ service footprint
$error.clear()
set-location I: 
$Test=$?

    If ($test -ne $true){

        [System.Windows.Forms.Application]::DoEvents()
        $localtest=hostname
        $localname=$source.substring(2,15)
        if ($localtest -ne $localname)
        {   
            net use N: $source
            $script:mountpoint="N:\$privatename"

            }
        else
        {
            $split1 = $source.split("/$")
            $split2 = $source.split("$")
            $locallocation = $split1[3] + ":" + $split2[1]
            $script:mountpoint="$locallocation\$privatename"
        }
            Mount-VHD  $mountpoint I
            $error.clear()
            set-location "I:\Windows"
            $Test=$?
        If ($test -eq $true){
            write-host "**Disk Mount Successful**"

            Return $mountpoint  
            [System.Windows.Forms.Application]::DoEvents()
            }
        else {
            write-host "**ALERT:  The Disk mounted has no bootable partition.  Please close application and check the Image.**"

            Dismount-VHD $mountpoint
            if ($mountpoint.substring(0,1) -eq "N")
            {
                net use N: /delete
            }
            Set-Location F:


            $Script:Cancelit=1
            Return $Cancelit

            }

            }
    else {
        Write-host "**ALERT:  There was a problem Mounting the vDisk.  Please close application and check the Disk Manager on the server to ensure the I: drive is available.**"

            $Script:Cancelit=1
            Return $Cancelit
        }

}#End Function
Function mount-Continue{param($location, $Disk, $server1) #Import-Module "F:\Scripts\LJ_Cleanup\mount.psm1"
# Script to use a mounted VHD to clean off the AppV service footprint
$error.clear()
set-location I:  $Test=$?

    If ($test -ne $true){
        net use /persistent:no
        #net use * /d

        write-host "Mounting VHD from $destination"
        $localtest=hostname
        if ($localtest -ne $server1)
        {   
            net use N: $location
            $Script:MC = "N:\$Disk"

            }
        else
        {
            $Script:MC = "F:\vdisks\$disk"

        }
        Mount-VHD $MC I
        $error.clear()
set-location "I:\Windows" $Test=$?

    If ($test -eq $true)
        {
            Write-host "**Disk Mount Successful**"
            Return $Disk  

            }
        else {
            Write-host "**ALERT:  The Disk mounted has no bootable partition.  Manually clean image and click ok to continue.**"

            $MsgBoxObj.Popup('**ALERT:  The Disk mounted has no bootable partition.  Manually clean image and click ok to continue.**')
            Return $Disk
            }

            }
    else {
        write-host "**ALERT:  There was a problem Mounting the vDisk.  Manually clean image and click ok to continue.**"
        $MsgBoxObj.Popup('**ALERT:  The Disk mounted has no bootable partition.  Manually clean image and click ok to continue.**')
        Return $Disk
        }

}#End Function
Function Dismount-it{
param ($Disk)
set-location F:
Dismount-VHD $disk
if ($Disk.substring(0,1) -eq "N")
{
    net use N: /delete
}
    $error.clear()
            set-location "I:\Windows"
            $Test=$?
        If ($test -ne $true)
        {
        Write-host " **Disk Successful Unmounted**"

        return

        }
    else {
        Write-host "**ALERT:  There was a problem unmounting the vDisk.  Please close application and troubleshoot.**"

        $Script:Cancelit=1
        Return $Cancelit
        }
}#End Function
Function Dismount-Continue{
set-location F:
Dismount-VHD $MC if ($MC.substring(0,1) -eq "N") {
    net use N: /delete

}           
    $error.clear()
            set-location "I:\Windows"
            $Test=$?
        If ($test -ne $true){
        Write-host " `r**Disk Successful Unmounted**"

        return

        }
    else {
        Write-host "**ALERT:  There was a problem unmounting the vDisk.  Manually clean image and click ok to continue.**"

        $MsgBoxObj.Popup('**ALERT:  There was a problem unmounting the vDisk.  Manually clean image and click ok to continue.**')
            Return $Disk
        }
}#End Function
Mount-it "\\server1pvs1\g$\vdisks" "image - private.vhd"
dir
Dismount-it $mountpoint
dir
Mount-it "\\server1pvs1\g$\vdisks" "image - private.vhd"
dir
Dismount-it $mountpoint

UPDATE: new-PSdrive doesn't allow you to mount a VHD (or atleast I haven't found a way). What I have found is that the problem I described above stems from using Test-path. Don't believe me, try this: Open a powershell session and mount your vhd (using the gui or diskpart), them run a 'test-path I:\' (or whatever comes up as your drive letter) it comes back as "true" (which is what you want). I dismount the disk and run 'test-path I:\' again and get "false". Still good feedback. I mount the disk again (or another disk) and run 'test-path I:\' again it comes back as "false" (should be "true") and you can't navigate to the drive letter within the powershell instance. If I open up a new session I can navigate to I: fine.

share|improve this question

1 Answer 1

There are multiple things in play here. The most important being that Powershell does not run in the same context as your Windows Explorer - so it doesn't know about drives attached there, and vice-versa.

Secondly, get rid of diskpart and use Powershell's own facilities. Have a look at "New-PSDrive" (http://technet.microsoft.com/en-us/library/hh849829.aspx) for a start.

Thirdly, it's possible that these operations are asynchronous, and you may have your script wait a bit until the drive letter is removed/attached. (Doesn't happen manually because you're slow enough compared to the script execution).

share|improve this answer
    
new-PSdrive doesn't allow you to mount a VHD (or atleast I haven't found a way). What I have found is that the problem I described above stems from using Test-path. Don't believe me, try this: –  Kyle Feb 13 at 15:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.