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