我在超级用户上找到了这篇文章,
我在那篇文章中使用了脚本的修改版本来有效地列出所有驱动器和各种信息:
function Get-AllDriveInfo {
$signature =
@'
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetVolumePathNamesForVolumeNameW([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName,
[MarshalAs(UnmanagedType.LPWStr)] [Out] StringBuilder lpszVolumeNamePaths, uint cchBuferLength,
ref UInt32 lpcchReturnLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr FindFirstVolume([Out] StringBuilder lpszVolumeName,
uint cchBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FindNextVolume(IntPtr hFindVolume, [Out] StringBuilder lpszVolumeName, uint cchBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);
'@;
Add-Type -MemberDefinition $signature -Name Win32Utils -Namespace PInvoke -Using PInvoke, System.Text;
[UInt32] $lpcchReturnLength = 0;
[UInt32] $Max = 65535
$sbVolumeName = New-Object System.Text.StringBuilder($Max, $Max)
$sbPathName = New-Object System.Text.StringBuilder($Max, $Max)
$sbMountPoint = New-Object System.Text.StringBuilder($Max, $Max)
[IntPtr] $volumeHandle = [PInvoke.Win32Utils]::FindFirstVolume($sbVolumeName, $Max)
do {
$volume = $sbVolumeName.toString()
$unused = [PInvoke.Win32Utils]::GetVolumePathNamesForVolumeNameW($volume, $sbMountPoint, $Max, [Ref] $lpcchReturnLength);
$ReturnLength = [PInvoke.Win32Utils]::QueryDosDevice($volume.Substring(4, $volume.Length - 1 - 4), $sbPathName, [UInt32] $Max);
if ($ReturnLength) {
$DriveLetter = ($sbMountPoint.toString() -replace ':\\','')
$VolumeData = Get-Volume -UniqueId $volume | Select-Object *
$PartitionData = Get-Partition -DriveLetter $DriveLetter | Select-Object *
[PSCustomObject]@{
DriveLetter = $DriveLetter
DevicePath = $sbPathName.ToString()
DiskNumber = $PartitionData.DiskNumber
HealthStatus = $VolumeData.HealthStatus
DriveType = $VolumeData.DriveType
FileSystem = $VolumeData.FileSystemType
AllocationUnitSize = $VolumeData.AllocationUnitSize
FriendlyLabel = $VolumeData.FileSystemLabel
Capacity = Format-Bytes -Bytes $VolumeData.Size
RemainingSpace = Format-Bytes -Bytes $VolumeData.SizeRemaining
VolumeName = $volume
GptType = $PartitionData.GptType
GUID = $PartitionData.Guid
IsActive = $PartitionData.IsActive
IsBoot = $PartitionData.IsBoot
IsDAX = $PartitionData.IsDAX
IsHidden = $PartitionData.IsHidden
IsOffline = $PartitionData.IsOffline
IsReadOnly = $PartitionData.IsReadOnly
IsShadowCopy = $PartitionData.IsShadowCopy
IsSystem = $PartitionData.IsSystem
MbrType = $PartitionData.MbrType
Offset = $PartitionData.Offset
}
} else {
Write-Output "No mountpoint found for: " + $volume
}
} while ([PInvoke.Win32Utils]::FindNextVolume([IntPtr] $volumeHandle, $sbVolumeName, $Max));
}
Get-AllDriveInfo
但我现在真正想要的是创建一个函数,仅列出传入驱动器的数据(以驱动器号格式或 DevicePath 格式 (
\Device\HarddiskvolumeX
)。
代码有点超出我的理解,所以我希望有人能指出我正确的方向。这个想法是:
function Get-SpecificDriveInfo {
param (
[Parameter(Mandatory,ParameterSetName="DriveLetter")]
$DriveLetter,
[Parameter(Mandatory,ParameterSetName="DevicePath")]
$DevicePath
)
... Code to isolate the drive and print information.
}
# Usage:
Get-SpecificDriveInfo -DevicePath '\Device\HarddiskVolume3'
Get-SpecificDriveInfo -DriveLetter 'C'
我知道我需要相当多的帮助,但我就是无法理解一些更高级的
PInvoke.Win32Utils
功能及其工作原理。
任何帮助将不胜感激!
实际上,变化会很小:
function Get-SpecificDriveInfo {
param (
[Parameter(Mandatory,ParameterSetName="DriveLetter")]
[String]$DriveLetter,
[Parameter(Mandatory,ParameterSetName="DevicePath")]
[String]$DevicePath
)
$signature =
@'
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool
GetVolumePathNamesForVolumeNameW([MarshalAs(UnmanagedType.LPWStr)] string lpszVolumeName,
[MarshalAs(UnmanagedType.LPWStr)] [Out] StringBuilder lpszVolumeNamePaths, uint cchBuferLength,
ref UInt32 lpcchReturnLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr FindFirstVolume([Out] StringBuilder lpszVolumeName,
uint cchBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FindNextVolume(IntPtr hFindVolume, [Out]
StringBuilder lpszVolumeName, uint cchBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder
lpTargetPath, int ucchMax);
'@;
Add-Type -MemberDefinition $signature -Name Win32Utils -Namespace PInvoke -Using PInvoke, System.Text;
[UInt32] $lpcchReturnLength = 0;
[UInt32] $Max = 65535
$sbVolumeName = New-Object System.Text.StringBuilder($Max, $Max)
$sbPathName = New-Object System.Text.StringBuilder($Max, $Max)
$sbMountPoint = New-Object System.Text.StringBuilder($Max, $Max)
[IntPtr] $volumeHandle = [PInvoke.Win32Utils]::FindFirstVolume($sbVolumeName, $Max)
do {
$volume = $sbVolumeName.toString()
$unused = [PInvoke.Win32Utils]::GetVolumePathNamesForVolumeNameW($volume, $sbMountPoint, $Max, [Ref] $lpcchReturnLength);
$ReturnLength = [PInvoke.Win32Utils]::QueryDosDevice($volume.Substring(4, $volume.Length - 1 - 4), $sbPathName, [UInt32] $Max);
if ($ReturnLength) {
$Drive_Letter = ($sbMountPoint.toString() -replace ':\\','')
$VolumeData = Get-Volume -UniqueId $volume | Select-Object *
$PartitionData = Get-Partition -DriveLetter $DriveLetter | Select-Object *
#my change
if ((($Drive_Letter -eq $DriveLetter) -and ($PSBoundParameters.ContainsKey('DriveLetter'))) -or (($sbPathName.ToString() -eq $DevicePath)) -and ($PSBoundParameters.ContainsKey('DevicePath'))) {
[PSCustomObject]@{
DriveLetter = $Drive_Letter
DevicePath = $sbPathName.ToString()
DiskNumber = $PartitionData.DiskNumber
HealthStatus = $VolumeData.HealthStatus
DriveType = $VolumeData.DriveType
FileSystem = $VolumeData.FileSystemType
AllocationUnitSize = $VolumeData.AllocationUnitSize
FriendlyLabel = $VolumeData.FileSystemLabel
Capacity = Format-Bytes -Bytes $VolumeData.Size
RemainingSpace = Format-Bytes -Bytes $VolumeData.SizeRemaining
VolumeName = $volume
GptType = $PartitionData.GptType
GUID = $PartitionData.Guid
IsActive = $PartitionData.IsActive
IsBoot = $PartitionData.IsBoot
IsDAX = $PartitionData.IsDAX
IsHidden = $PartitionData.IsHidden
IsOffline = $PartitionData.IsOffline
IsReadOnly = $PartitionData.IsReadOnly
IsShadowCopy = $PartitionData.IsShadowCopy
IsSystem = $PartitionData.IsSystem
MbrType = $PartitionData.MbrType
Offset = $PartitionData.Offset
}
}
} else {
Write-Output "No mountpoint found for: " + $volume
}
} while ([PInvoke.Win32Utils]::FindNextVolume([IntPtr] $volumeHandle, $sbVolumeName, $Max));
}
# Usage:
Get-SpecificDriveInfo -DevicePath '\Device\HarddiskVolume3'
Get-SpecificDriveInfo -DriveLetter 'C'
我添加了一个比较块,用于检查是否给出了参数以及它等于什么。