Diskpart quebra letras de unidade após o script do PowerShell ser executado

4

Eu criei um script que monta (anexa) um VHD usando o Diskpart, limpa alguns arquivos do sistema e, em seguida, desmonta (desanexa) o arquivo. Ele usa um loop foreach e é suposto limpar vários VHD usando a mesma letra de unidade. No entanto, após o primeiro VHD, ele falha. Também notei que quando tento anexar manualmente um VHD com diskpart, o diskpart é bem-sucedido, o Disk Manager mostra o disco com a letra da unidade correta, mas dentro da mesma instância PoSH, não consigo conectar (set-location) a essa unidade. Se eu fizer um diskpart manual quando eu abrir o PoSH, dentro dessa instância, posso anexar e desanexar tudo o que quero e recebo a letra da unidade toda vez, mas no minuto em que executo o script, a letra da unidade é destruída na instância após usar. Existe algo que eu preciso fazer para redefinir o diskpart no script? Aqui está um trecho do script que estou usando.

$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 não permite montar um VHD (ou pelo menos eu não encontrei um caminho). O que eu descobri é que o problema que descrevi acima vem do uso do Test-path. Não acredite em mim, tente isto: Abra uma sessão do powershell e monte seu vhd (usando o gui ou o diskpart), eles executam um 'test-path I: \' (ou o que aparecer como letra de sua unidade). "true" (que é o que você quer). Eu desmonto o disco e executo 'test-path I: \' novamente e obtenho "false". Ainda bom feedback. Monto o disco novamente (ou outro disco) e executo 'test-path I: \' novamente ele retorna como "false" (deve ser "true") e você não pode navegar para a letra da unidade dentro da instância do powershell. Se eu abrir uma nova sessão, posso navegar para I: fine.

    
por Kyle 18.12.2012 / 16:26

1 resposta

1

Há várias coisas em jogo aqui. O mais importante é que o Powershell não seja executado no mesmo contexto que o seu Windows Explorer - portanto, ele não sabe sobre as unidades conectadas e vice-versa.

Em segundo lugar, livre-se do diskpart e use as próprias instalações do Powershell. Dê uma olhada no "New-PSDrive" ( link ) para começar.

Em terceiro lugar, é possível que essas operações sejam assíncronas e você pode ter seu script aguardando um pouco até que a letra da unidade seja removida / anexada. (Não acontece manualmente porque você é lento o suficiente em comparação com a execução do script).

    
por 21.02.2013 / 13:49