Назад | Перейти на главную страницу

Diskpart ломает буквы дисков после запуска сценария powershell

Я создал сценарий, который монтирует (присоединяет) VHD с помощью Diskpart, очищает некоторые системные файлы, а затем размонтирует (отключает) его. Он использует цикл foreach и предполагает очистку нескольких VHD с использованием одной и той же буквы диска. Однако после 1-го VHD он не работает. Я также заметил, что когда я пытаюсь вручную подключить виртуальный жесткий диск с помощью diskpart, diskpart завершается успешно, диспетчер дисков показывает диск с правильной буквой диска, но в том же экземпляре PoSH я не могу подключиться (установить местоположение) к этому диску. Если я делаю дисковую часть вручную при первом открытии PoSH, в этом экземпляре я могу присоединять и отсоединять все, что хочу, и каждый раз получать букву диска, но в ту минуту, когда я запускаю скрипт, буква диска уничтожается в экземпляре после использовать. Что мне нужно сделать, чтобы сбросить diskpart в скрипте? Вот фрагмент скрипта, который я использую.

$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

ОБНОВЛЕНИЕ: new-PSdrive не позволяет монтировать VHD (или, по крайней мере, я не нашел способа). Я обнаружил, что проблема, которую я описал выше, связана с использованием Test-path. Не верьте мне, попробуйте следующее: откройте сеанс PowerShell и смонтируйте свой vhd (используя gui или diskpart), они запускают 'test-path I: \' (или что-то еще, что появляется как буква вашего диска), он возвращается как "правда" (чего вы и хотите). Я отключаю диск и снова запускаю 'test-path I: \' и получаю «false». По-прежнему хорошие отзывы. Я снова монтирую диск (или другой диск) и запускаю 'test-path I: \', он снова возвращается как «false» (должно быть «true»), и вы не можете перейти к букве диска в экземпляре powershell. Если я открываю новый сеанс, я могу перейти к I: хорошо.

Здесь задействовано несколько вещей. Самым важным является то, что Powershell не работает в том же контексте, что и ваш проводник Windows, поэтому он не знает о подключенных к нему дисках, и наоборот.

Во-вторых, избавьтесь от diskpart и используйте собственные средства Powershell. Взгляните на "New-PSDrive" (http://technet.microsoft.com/en-us/library/hh849829.aspx) для начала.

В-третьих, возможно, что эти операции являются асинхронными, и ваш скрипт может немного подождать, пока буква диска не будет удалена / прикреплена. (Это не происходит вручную, потому что вы достаточно медленны по сравнению с выполнением скрипта).