Powershell проверить, существует ли буква диска и, если да, удалить - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть скрипт, который проверяет, есть ли диски с определенными буквами. Если это письмо существует, оно удалит это письмо. Затем скрипт выполняет поиск дисков в соответствии с их «метками», изменяя их буквы в соответствии с тем, что указано в скрипте.

Я пытаюсь усовершенствовать сценарий, чтобы в первой части он искал любые диски с буквами E или D и, если это так, удалил их. Если он не найден, то просто перейдите ко второй части изменения в соответствии с меткой диска.

Get-Volume -DriveLetter E | Get-Partition | Remove-PartitionAccessPath -AccessPath E:\
Get-Volume -DriveLetter D | Get-Partition | Remove-PartitionAccessPath -AccessPath D:\

$DataPartition = Get-WMIObject Win32_Volume | where{ $_.Label -eq 'Data'}
$FileServerPartition = Get-WMIObject Win32_Volume | where{ $_.Label -eq 'FileServer'}

$DataPartition.DriveLetter = $null
$DataPartition.Put()
$FileServerPartition.DriveLetter = $null
$FileServerPartition.Put()


Try
{
    Set-WmiInstance -input $DataPartition -Arguments @{DriveLetter="D:"} | Out-File -FilePath  C:\Windows\Temp\FixPartitionsLog.txt -Append
    Set-WmiInstance -input $FileServerPartition -Arguments @{DriveLetter="E:"} | Out-File -FilePath  C:\Windows\Temp\FixPartitionsLog.txt -Append
}
Catch
{
    $ErrorMessage = $_.Exception.Message | Out-File -FilePath C:\Windows\Temp\FixPartitionsLog.txt
}
sleep 5
Restart-Service server -Force

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

У меня уже была функция, выполняющая то, что вы хотите.
Я включил его как есть, но на самом деле вам нужно всего 5 строк.
И есть небольшое отличие от того, что вы спросили. Удаляются только буквы для найденных ярлыков.
например Если метка «Данные» не найдена, но существует «D: \», буква «D» не будет удалена.

[CmdletBinding()]
param()
function Set-Partition_NewDriveLetter_Force {
    param(
      [Parameter(ValueFromPipeline = $true)][Alias('InputObject')]
      $DiskPartition,
      [Parameter(Mandatory = $true)]
      [System.Char]$NewDriveLetter
    )
      # if (Test-Path -LiteralPath "${NewDriveLetter}:\") { # will error if letter does not exist
      # if (Get-Volume -DriveLetter $NewDriveLetter) {      # will error if letter does not exist
      if (Get-Volume -FilePath "${NewDriveLetter}:\") {
          if ($DiskPartition.DriveLetter -ne $NewDriveLetter) {
              Write-Verbose "Letter $NewDriveLetter is already taken by other volume, removing and adding to detected volume..."
              Remove-PartitionAccessPath -DriveLetter $NewDriveLetter -AccessPath "${NewDriveLetter}:\"
              Set-Partition -InputObject $DiskPartition -NewDriveLetter $NewDriveLetter
          } else { Write-Verbose "Letter $NewDriveLetter is already assigned to this volume." }
      } else {
          Write-Verbose "Letter $NewDriveLetter is being assigned to detected volume."
          Set-Partition -InputObject $DiskPartition -NewDriveLetter $NewDriveLetter
      }
  }


foreach ($p in Get-Volume | Where-Object { $_.FileSystemLabel -in 'Recovery', 'SYSTEM' }) {
    Write-Host "Found drive with Label: $($p.FileSystemLabel)"
    switch ($p.FileSystemLabel) {
        'Recovery' { $p | Get-Partition | Set-Partition_NewDriveLetter_Force -NewDriveLetter 'R' }
        'SYSTEM' { $p | Get-Partition | Set-Partition_NewDriveLetter_Force -NewDriveLetter 'S' }
    }
}

Использование:

Если он был сохранен в файл ps1 и вызван с аргументом -Verbose, он покажет больше вывода.

Пояснение:

Я назвал функцию и включил параметры, похожие на командлет, выполняющий аналогичную функцию.

Первые две строки включают «расширенную функцию» для блока скрипта. Это нужно только для работы -Verbose.

Как видно из комментариев, Get-Volume -FilePath 'X:\' - единственный способ найти ошибку, если буква тома отсутствует. (Get-Volume).DriveLetter также выдаст ошибку, если букв нет, но это маловероятно.

Я ограничиваю количество запросов к диску, хотя это может на самом деле не увеличивать скорость.

Примечание к вашему ответу:

Вам не нужно if ($driveLetters -contains "d" -or $driveLetters -contains "e") когда за ним следует switch, который в данном случае также является условным оператором, выполняющим ту же работу.

Вам не нужны и Get-Volume, и Get-Partition, поскольку Get-Partition также имеет аргумент -DriveLetter:
"d" { Get-Partition -DriveLetter D | Remove-PartitionAccessPath -AccessPath D:\ }

Вам не нужен WMI для чтения меток, Get-Volume имеет свойство Label.
Иногда может быть быстрее использовать .NET или WMI напрямую, в отличие от вызова командлетов PS, но есть причины не смешивать их, пока нет другого пути.

0 голосов
/ 11 ноября 2018

Это было решение, которое я использовал в конце:

$driveLetters= (Get-Volume).DriveLetter
if ($driveLetters -contains "d" -or $driveLetters -contains "e")
{
switch ($driveLetters)
{
    "d" {Get-Volume -DriveLetter D | Get-Partition | Remove-PartitionAccessPath -AccessPath D:\}
    "e" {Get-Volume -DriveLetter E | Get-Partition | Remove-PartitionAccessPath -AccessPath E:\}
}
}

$DataPartition = Get-WMIObject Win32_Volume | where{ $_.Label -eq 'Data'}
$FileServerPartition = Get-WMIObject Win32_Volume | where{ $_.Label -eq 'FileServer'}

$DataPartition.DriveLetter = $null
$DataPartition.Put()
$FileServerPartition.DriveLetter = $null
$FileServerPartition.Put()



Try
{
    Set-WmiInstance -input $DataPartition -Arguments @{DriveLetter="D:"} | Out-File -FilePath  C:\Windows\Temp\FixPartitionsLog.txt -Append
    Set-WmiInstance -input $FileServerPartition -Arguments @{DriveLetter="E:"} | Out-File -FilePath  C:\Windows\Temp\FixPartitionsLog.txt -Append

}
Catch
{
    $ErrorMessage = $_.Exception.Message | Out-File -FilePath C:\Windows\Temp\FixPartitionsLog.txt
}
sleep 5
Restart-Service server -Force
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...