지금은 다음 두 WMI 쿼리를 사용하여 컴퓨터의 드라이브에 대한 정보를 가져오고 있습니다.
get-wmiObject -Class Win32_LogicalDisk -Namespace root\CIMV2
-Computername $name
get-wmiObject -Class Win32_DiskDrive -Namespace root\CIMV2
-Computername $name
첫 번째는 드라이브 문자를 참조하는 DeviceID를 제공하고 그런 다음 해당 드라이브에 대한 일부 정보(볼륨 일련 번호 등 포함)를 제공합니다.
두 번째는 \\\\.\\PHYSICALDRIVE#
일련 번호(다른 것 같음) 파티션, 인덱스, scsi 포트/ID 등에 매핑되는 DeviceID를 제공합니다.
Win32_DiskDriveToDiskPartition
또한 디스크 번호, 파티션 번호, 디스크 인덱스와 같은 정보를 제공하는 것도 보았습니다 .
Win32_DiskDrive
내 질문은 DeviceID가 어디에서나 볼륨으로 매핑되었는지 확인하고 해당 볼륨(또는 해당 볼륨)이 무엇인지 확인하는 쿼리할 수 있는 방법/공통 값이 있다는 것입니다 .
방법이 있어야 한다는 것을 알고 있습니다. Win32 개체가 너무 많아서 어떤 값을 추적해야 할지 잘 모르겠습니다. 어떤 도움이라도 큰 도움이 될 것입니다! 이상적으로는 컴퓨터 이름을 호출하고 모든 디스크 장치, 모든 볼륨을 나열하고 어떤 드라이브에 어떤 볼륨 문자가 있는지 나타내는 기능을 정의할 수 있기를 바랍니다.
답변1
마운팅된 드라이브 장치 ID를 볼륨 문자에 매핑하는 Powershell/WMI
내 질문은 Win32_DiskDrive의 DeviceID가 어디에서나 볼륨으로 매핑되었는지 확인하고 해당 볼륨(또는 해당 볼륨)이 무엇인지 확인하는 쿼리할 수 있는 방법/공통 값이 있습니까?
그럴 것 같다Win32_Volume 클래스당신이 사용해야 할 것입니다. DeviceID와 드라이브 문자 값을 모두 제공합니다.
예제 PowerShell 구문 1
get-wmiObject -Class Win32_Volume -Namespace root\CIMV2 | Format-List -Property Name, DriveLetter, __Path, DeviceID
예제 PowerShell 구문 2
get-wmiObject -Class Win32_Volume -Namespace root\CIMV2
내 질문은 Win32_DiskDrive의 DeviceID가 어디에서나 볼륨으로 매핑되었는지 확인하고 해당 볼륨(또는 해당 볼륨)이 무엇인지 확인하는 쿼리할 수 있는 방법/공통 값이 있습니까?
방법이 있어야 한다는 것을 알고 있습니다. Win32 개체가 너무 많아서 어떤 값을 추적해야 할지 잘 모르겠습니다. 어떤 도움이라도 큰 도움이 될 것입니다! 이상적으로는 컴퓨터 이름을 호출하고 모든 디스크 장치, 모든 볼륨을 나열하고 어떤 드라이브에 어떤 볼륨 문자가 있는지 나타내는 기능을 정의할 수 있기를 바랍니다.
Technet 갤러리 - Powershell
(아래의 PowerShell 스크립트를 함수로 제공합니다. 이를 로컬에서 실행하거나 원격 컴퓨터에 대해 실행할 수 있습니다. 자세한 내용은 소스에서 하이퍼링크를 참조하세요.)
함수를 빌드한 후에는 몇 가지 다른 방법을 실행하면 됩니다.
Get-RemoteDiskInformation
로컬 디스크 및 볼륨 세부 정보를 보려면 Enter 키를 누르세요.Get-RemoteDiskInformation -ComputerName <ComputerName>
원격 시스템의 디스크 및 볼륨 세부 정보를 얻으려면
PowerShell 함수 논리
Function Get-RemoteDiskInformation
{
<#
.SYNOPSIS
Get inventory data for specified computer systems.
.DESCRIPTION
Gather inventory data for one or more systems using wmi. Data proccessing utilizes multiple runspaces
and supports custom timeout parameters in case of wmi problems. You can optionally include
drive, memory, and network information in the results. You can view verbose information on each
runspace thread in realtime with the -Verbose option.
.PARAMETER ComputerName
Specifies the target computer for data query.
.PARAMETER ThrottleLimit
Specifies the maximum number of systems to inventory simultaneously
.PARAMETER Timeout
Specifies the maximum time in second command can run in background before terminating this thread.
.PARAMETER ShowProgress
Show progress bar information
.PARAMETER PromptForCredential
Prompt for remote system credential prior to processing request.
.PARAMETER Credential
Accept alternate credential (ignored if the localhost is processed)
.EXAMPLE
PS > Get-RemoteDiskInformation -ComputerName test1
Description
-----------
Query and display disk related information about test1
.EXAMPLE
PS > $cred = Get-Credential
PS > Get-RemoteDiskInformation -ComputerName Test1 -Credential $cred
.NOTES
Author:
Zachary Loeber
Version Info:
1.1 - 01/04/2014
- Added missing computername property to diskelements variable
1.0 - 12/13/2013
- Initial release (kind of, this bit of code is modified from a prior function I rolled into an all inclusive system information gathering
function).
.LINK
http://www.the-little-things.net
#>
[CmdletBinding()]
PARAM
(
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateNotNullOrEmpty()]
[Alias('DNSHostName','PSComputerName')]
[string[]]
$ComputerName=$env:computername,
[Parameter( HelpMessage="Refrain from applying drive space GB/MB/KB pretty formatting.")]
[switch]
$RawDriveData,
[Parameter(HelpMessage="Maximum number of concurrent runspaces.")]
[ValidateRange(1,65535)]
[int32]
$ThrottleLimit = 32,
[Parameter(HelpMessage="Timeout before a runspaces stops trying to gather the information.")]
[ValidateRange(1,65535)]
[int32]
$Timeout = 120,
[Parameter(HelpMessage="Display progress of function.")]
[switch]
$ShowProgress,
[Parameter(HelpMessage="Set this if you want the function to prompt for alternate credentials.")]
[switch]
$PromptForCredential,
[Parameter(HelpMessage="Set this if you want to provide your own alternate credentials.")]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty
)
BEGIN
{
# Gather possible local host names and IPs to prevent credential utilization in some cases
Write-Verbose -Message 'Get-RemoteDiskInformation: Creating local hostname list'
$IPAddresses = [net.dns]::GetHostAddresses($env:COMPUTERNAME) | Select-Object -ExpandProperty IpAddressToString
$HostNames = $IPAddresses | ForEach-Object {
try {
[net.dns]::GetHostByAddress($_)
} catch {
# We do not care about errors here...
}
} | Select-Object -ExpandProperty HostName -Unique
$LocalHost = @('', '.', 'localhost', $env:COMPUTERNAME, '::1', '127.0.0.1') + $IPAddresses + $HostNames
Write-Verbose -Message 'Get-RemoteDiskInformation: Creating initial variables'
$runspacetimers = [HashTable]::Synchronized(@{})
$runspaces = New-Object -TypeName System.Collections.ArrayList
$bgRunspaceCounter = 0
if ($PromptForCredential)
{
$Credential = Get-Credential
}
Write-Verbose -Message 'Get-RemoteDiskInformation: Creating Initial Session State'
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
foreach ($ExternalVariable in ('runspacetimers', 'Credential', 'LocalHost'))
{
Write-Verbose -Message "Get-RemoteDiskInformation: Adding variable $ExternalVariable to initial session state"
$iss.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $ExternalVariable, (Get-Variable -Name $ExternalVariable -ValueOnly), ''))
}
Write-Verbose -Message 'Get-RemoteDiskInformation: Creating runspace pool'
$rp = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1, $ThrottleLimit, $iss, $Host)
$rp.ApartmentState = 'STA'
$rp.Open()
# This is the actual code called for each computer
Write-Verbose -Message 'Get-RemoteDiskInformation: Defining background runspaces scriptblock'
$ScriptBlock =
{
[CmdletBinding()]
Param
(
[Parameter(Position=0)]
[string]
$ComputerName,
[Parameter(Position=1)]
[int]
$bgRunspaceID,
[Parameter(Position=2)]
[switch]
$RawDriveData
)
$runspacetimers.$bgRunspaceID = Get-Date
try
{
Write-Verbose -Message ('Get-RemoteDiskInformation: Runspace {0}: Start' -f $ComputerName)
$WMIHast = @{
ComputerName = $ComputerName
ErrorAction = 'Stop'
}
if (($LocalHost -notcontains $ComputerName) -and ($Credential -ne $null))
{
$WMIHast.Credential = $Credential
}
Filter ConvertTo-KMG
{
<#
.Synopsis
Converts byte counts to Byte\KB\MB\GB\TB\PB format
.DESCRIPTION
Accepts an [int64] byte count, and converts to Byte\KB\MB\GB\TB\PB format
with decimal precision of 2
.EXAMPLE
3000 | convertto-kmg
#>
$bytecount = $_
switch ([math]::truncate([math]::log($bytecount,1024)))
{
0 {"$bytecount Bytes"}
1 {"{0:n2} KB" -f ($bytecount / 1kb)}
2 {"{0:n2} MB" -f ($bytecount / 1mb)}
3 {"{0:n2} GB" -f ($bytecount / 1gb)}
4 {"{0:n2} TB" -f ($bytecount / 1tb)}
Default {"{0:n2} PB" -f ($bytecount / 1pb)}
}
}
Write-Verbose -Message ('Get-RemoteDiskInformation: Runspace {0}: Disk information' -f $ComputerName)
$WMI_DiskMountProps = @('Name','Label','Caption','Capacity','FreeSpace','Compressed','PageFilePresent','SerialNumber')
# WMI data
$wmi_diskdrives = Get-WmiObject @WMIHast -Class Win32_DiskDrive
$wmi_mountpoints = Get-WmiObject @WMIHast -Class Win32_Volume -Filter "DriveType=3 AND DriveLetter IS NULL" |
Select $WMI_DiskMountProps
$AllDisks = @()
$DiskElements = @('ComputerName','Disk','Model','Partition','Description','PrimaryPartition','VolumeName','Drive','DiskSize','FreeSpace','UsedSpace','PercentFree','PercentUsed','DiskType','SerialNumber')
foreach ($diskdrive in $wmi_diskdrives)
{
$partitionquery = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($diskdrive.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
$partitions = @(Get-WmiObject @WMIHast -Query $partitionquery)
foreach ($partition in $partitions)
{
$logicaldiskquery = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($partition.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"
$logicaldisks = @(Get-WmiObject @WMIHast -Query $logicaldiskquery)
foreach ($logicaldisk in $logicaldisks)
{
$PercentFree = [math]::round((($logicaldisk.FreeSpace/$logicaldisk.Size)*100), 2)
$UsedSpace = ($logicaldisk.Size - $logicaldisk.FreeSpace)
$diskprops = @{
ComputerName = $ComputerName
Disk = $diskdrive.Name
Model = $diskdrive.Model
Partition = $partition.Name
Description = $partition.Description
PrimaryPartition = $partition.PrimaryPartition
VolumeName = $logicaldisk.VolumeName
Drive = $logicaldisk.Name
DiskSize = if ($RawDriveData) { $logicaldisk.Size } else { $logicaldisk.Size | ConvertTo-KMG }
FreeSpace = if ($RawDriveData) { $logicaldisk.FreeSpace } else { $logicaldisk.FreeSpace | ConvertTo-KMG }
UsedSpace = if ($RawDriveData) { $UsedSpace } else { $UsedSpace | ConvertTo-KMG }
PercentFree = $PercentFree
PercentUsed = [math]::round((100 - $PercentFree),2)
DiskType = 'Partition'
SerialNumber = $diskdrive.SerialNumber
}
Write-Output (New-Object psobject -Property $diskprops | Select $DiskElements)
}
}
}
# Mountpoints are weird so we do them seperate.
if ($wmi_mountpoints)
{
foreach ($mountpoint in $wmi_mountpoints)
{
$PercentFree = [math]::round((($mountpoint.FreeSpace/$mountpoint.Capacity)*100), 2)
$UsedSpace = ($mountpoint.Capacity - $mountpoint.FreeSpace)
$diskprops = @{
ComputerName = $ComputerName
Disk = $mountpoint.Name
Model = ''
Partition = ''
Description = $mountpoint.Caption
PrimaryPartition = ''
VolumeName = ''
VolumeSerialNumber = ''
Drive = [Regex]::Match($mountpoint.Caption, "(^.:)").Value
DiskSize = if ($RawDriveData) { $mountpoint.Capacity } else { $mountpoint.Capacity | ConvertTo-KMG }
FreeSpace = if ($RawDriveData) { $mountpoint.FreeSpace } else { $mountpoint.FreeSpace | ConvertTo-KMG }
UsedSpace = if ($RawDriveData) { $UsedSpace } else { $UsedSpace | ConvertTo-KMG }
PercentFree = $PercentFree
PercentUsed = [math]::round((100 - $PercentFree),2)
DiskType = 'MountPoint'
SerialNumber = $mountpoint.SerialNumber
}
Write-Output (New-Object psobject -Property $diskprops | Select $DiskElements)
}
}
}
catch
{
Write-Warning -Message ('Get-RemoteDiskInformation: {0}: {1}' -f $ComputerName, $_.Exception.Message)
}
Write-Verbose -Message ('Get-RemoteDiskInformation: Runspace {0}: End' -f $ComputerName)
}
function Get-Result
{
[CmdletBinding()]
Param
(
[switch]$Wait
)
do
{
$More = $false
foreach ($runspace in $runspaces)
{
$StartTime = $runspacetimers[$runspace.ID]
if ($runspace.Handle.isCompleted)
{
Write-Verbose -Message ('Get-RemoteDiskInformation: Thread done for {0}' -f $runspace.IObject)
$runspace.PowerShell.EndInvoke($runspace.Handle)
$runspace.PowerShell.Dispose()
$runspace.PowerShell = $null
$runspace.Handle = $null
}
elseif ($runspace.Handle -ne $null)
{
$More = $true
}
if ($Timeout -and $StartTime)
{
if ((New-TimeSpan -Start $StartTime).TotalSeconds -ge $Timeout -and $runspace.PowerShell)
{
Write-Warning -Message ('Timeout {0}' -f $runspace.IObject)
$runspace.PowerShell.Dispose()
$runspace.PowerShell = $null
$runspace.Handle = $null
}
}
}
if ($More -and $PSBoundParameters['Wait'])
{
Start-Sleep -Milliseconds 100
}
foreach ($threat in $runspaces.Clone())
{
if ( -not $threat.handle)
{
Write-Verbose -Message ('Get-RemoteDiskInformation: Removing {0} from runspaces' -f $threat.IObject)
$runspaces.Remove($threat)
}
}
if ($ShowProgress)
{
$ProgressSplatting = @{
Activity = 'Get-RemoteDiskInformation: Getting asset info'
Status = '{0} of {1} total threads done' -f ($bgRunspaceCounter - $runspaces.Count), $bgRunspaceCounter
PercentComplete = ($bgRunspaceCounter - $runspaces.Count) / $bgRunspaceCounter * 100
}
Write-Progress @ProgressSplatting
}
}
while ($More -and $PSBoundParameters['Wait'])
}
}
PROCESS
{
foreach ($Computer in $ComputerName)
{
$bgRunspaceCounter++
$psCMD = [System.Management.Automation.PowerShell]::Create().AddScript($ScriptBlock)
$null = $psCMD.AddParameter('bgRunspaceID',$bgRunspaceCounter)
$null = $psCMD.AddParameter('ComputerName',$Computer)
$null = $psCMD.AddParameter('RawDriveData',$RawDriveData)
$null = $psCMD.AddParameter('Verbose',$VerbosePreference) # Passthrough the hidden verbose option so write-verbose works within the runspaces
$psCMD.RunspacePool = $rp
Write-Verbose -Message ('Get-RemoteDiskInformation: Starting {0}' -f $Computer)
[void]$runspaces.Add(@{
Handle = $psCMD.BeginInvoke()
PowerShell = $psCMD
IObject = $Computer
ID = $bgRunspaceCounter
})
Get-Result
}
}
END
{
Get-Result -Wait
if ($ShowProgress)
{
Write-Progress -Activity 'Get-RemoteDiskInformation: Getting asset info' -Status 'Done' -Completed
}
Write-Verbose -Message "Get-RemoteDiskInformation: Closing runspace pool"
$rp.Close()
$rp.Dispose()
}
}
약간의 테스트와 읽기를 통해 이 기능을 확장하여 다른 WMI 클래스와 연결할 값에서 더 자세한 정보를 얻을 수 있습니다. 다음은 해당 작업의 시작점에 대한 귀하의 문의와 관련된 좋은 세부 정보를 제공하기 위해 제가 찾은 몇 가지입니다.
Get-WMIObject -Class Win32_Volume | Select-Object -Property *
Get-WMIObject -Class Win32_DiskDrive | Select-Object -Property *
Get-WmiObject -Class Win32_DiskPartition | Select-Object -Property *
Get-WMIObject -Class Win32_LogicalDisk | Select-Object -Property *
Get-WMIObject -Class Win32_LogicalDiskToPartition | Select-Object -Property *