运行 powershell 脚本后,Diskpart 破坏驱动器号

运行 powershell 脚本后,Diskpart 破坏驱动器号

我编写了一个脚本,使用 Diskpart 挂载(连接)VHD,清除一些系统文件,然后卸载(分离)它。它使用 foreach 循环,并假设使用相同的驱动器号清理多个 VHD。但是,在第一个 VHD 之后,它失败了。我还注意到,当我尝试使用 diskpart 手动连接 VHD 时,diskpart 成功了,磁盘管理器显示具有正确驱动器号的磁盘,但在同一个 PoSH 实例中,我无法连接(设置位置)到该驱动器。如果我第一次打开 PoSH 时执行手动 diskpart,在该实例中,我可以连接和分离我想要的所有内容,并且每次都会获得驱动器号,但是当我运行脚本时,驱动器号在使用后会在实例中被破坏。我需要做些什么来重置脚本中的 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:\”(或任何作为您的驱动器号出现的内容),它返回“true”(这是您想要的)。我卸载磁盘并再次运行“test-path I:\”,结果显示“false”。仍然得到很好的反馈。我再次安装磁盘(或另一个磁盘)并再次运行“test-path I:\”,它返回“false”(应该是“true”),您无法在 powershell 实例中导航到驱动器号。如果我打开一个新会话,我可以导航到 I:很好。

答案1

这里有多种因素。最重要的是,Powershell 并不在与 Windows 资源管理器相同的环境中运行 - 因此它不知道连接到那里的驱动器,反之亦然。

其次,删除 diskpart 并使用 Powershell 自己的功能。查看“New-PSDrive”(http://technet.microsoft.com/en-us/library/hh849829.aspx) 作为一个开始。

第三,这些操作可能是异步的,您可能需要让脚本等待一段时间,直到驱动器号被删除/附加。(不会手动发生,因为与脚本执行相比,您的速度已经足够慢了)。

相关内容