PowerShell function to get disk SCSI Lun number
May 29, 2012 6 Comments
For our Boot From SAN servers we wanted to know the SCSI Lun number of the disks. You can get this information via WMI. But to retrieve it you need four different WMI objects. I made a PowerShell advanced function that combines these four WMI objects to relate the disk with the LUN number.
The Get-DiskScsiLun function
The Get-DiskScsiLun function uses the following WMI objects:
Win32_LogicalDisk, Win32_LogicalDiskToPartition, Win32_DiskDriveToDiskPartition and Win32_DiskDrive.
The first object contains the drive letter. The last object contains the Lun number. And the two other objects are needed to relate the drive letter to the Lun number.
function Get-DiskScsiLun {
<#
.SYNOPSIS
Retrieves the SCSI Lun information for a disk.
.DESCRIPTION
Retrieves the SCSI Lun information for a disk.
.PARAMETER DeviceID
Specify the disk name for wich the Scsi Lun information should be retrieved.
.PARAMETER ComputerName
Specifies the computer against which you want to run the management operation.
The value can be a fully qualified domain name, a NetBIOS name, or an IP
address. Use the local computer name, use localhost, or use a dot (.) to specify the local
computer. The local computer is the default.
When the remote computer is in a different domain from the user, you must use a fully
qualified domain name. This parameter can also be piped to the cmdlet.
This parameter does not rely on Windows PowerShell remoting, which uses WS-Management.
You can use the ComputerName parameter of Get-WmiObject even if your computer is not
configured to run WS-Management remote commands.
.PARAMETER Credential
Specifies a user account that has permission to perform this action. The default is
the current user. Type a user name, such as "User01", "Domain01\User01",
or User@Contoso.com. Or, enter a PSCredential object, such as an object that is
returned by the Get-Credential cmdlet. When you type a user name, you will be prompted
for a password.
.EXAMPLE
PS C:\> Get-DiskScsiLun
.EXAMPLE
PS C:\> Get-DiskScsiLun -DeviceID C: -ComputerName Server01 -Credential Domain01\User01
.EXAMPLE
PS C:\> "Server01","Server02" | Get-DiskScsiLun -Credential Domain01\User01
.INPUTS
System.String,PSCredential
.OUTPUTS
PSObject
.NOTES
Author: Robert van den Nieuwendijk
Version: 1.1
Date: 17-1-2013
.LINK
http://rvdnieuwendijk.com/
#>
[CmdletBinding()]
param([Parameter(Mandatory = $false,
Position = 0)]
[alias("Disk")]
[string] $DeviceID = '*',
[Parameter(Mandatory = $false,
Position = 1,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[alias("CN")]
[String[]] $ComputerName = $env:COMPUTERNAME,
[Parameter(Mandatory=$false,
Position = 2)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty
)
process {
if ($ComputerName)
{
# Loop through all computers in the parameter list
foreach ($Computer in $ComputerName) {
try {
if ($Computer -eq "$($env:COMPUTERNAME)" -or $Computer -eq "." -or $Computer -eq "localhost")
{
# Define the Get-WmiObject parameter set for the local computer
$Parameters = @{
Impersonation = 3
ErrorAction = 'Stop'
}
}
else
{
# Define the Get-WmiObject parameter set for remote computers
$Parameters = @{
ComputerName = $Computer
Credential = $Credential
ErrorAction = 'Stop'
}
}
# Test if the computer can be connected
if (Test-Connection -ComputerName $Computer -Count 1 -Quiet)
{
# Get the WMI objects
$Win32_LogicalDisk = Get-WmiObject -Class Win32_LogicalDisk @Parameters |
Where-Object {$_.DeviceID -like $DeviceID}
$Win32_LogicalDiskToPartition = Get-WmiObject -Class Win32_LogicalDiskToPartition @Parameters
$Win32_DiskDriveToDiskPartition = Get-WmiObject -Class Win32_DiskDriveToDiskPartition @Parameters
$Win32_DiskDrive = Get-WmiObject -Class Win32_DiskDrive @Parameters
# Search the SCSI Lun Unit for the disk
$Win32_LogicalDisk |
ForEach-Object {
if ($_)
{
$LogicalDisk = $_
$LogicalDiskToPartition = $Win32_LogicalDiskToPartition |
Where-Object {$_.Dependent -eq $LogicalDisk.Path}
if ($LogicalDiskToPartition)
{
$DiskDriveToDiskPartition = $Win32_DiskDriveToDiskPartition |
Where-Object {$_.Dependent -eq $LogicalDiskToPartition.Antecedent}
if ($DiskDriveToDiskPartition)
{
$DiskDrive = $Win32_DiskDrive |
Where-Object {$_.__Path -eq $DiskDriveToDiskPartition.Antecedent}
if ($DiskDrive)
{
# Return the results
New-Object -TypeName PSObject -Property @{
Computer = $Computer
DeviceID = $LogicalDisk.DeviceID
SCSIBus = $DiskDrive.SCSIBus
SCSIPort = $DiskDrive.SCSIPort
SCSITargetId = $DiskDrive.SCSITargetId
SCSILogicalUnit = $DiskDrive.SCSILogicalUnit
}
}
}
}
}
}
}
else
{
Write-Warning "Unable to connect to computer $Computer."
}
}
catch {
Write-Warning "Unable to get disk information for computer $Computer.`n$($_.Exception.Message)"
}
}
}
}
}
Listing 1. The PowerShell advanced function Get-DiskScsiLun that retrieves the SCSI Lun number for a disk.
Annotations
Line 79-95: Build the parameter sets for the Get-WmiObject function calls.
Line 100-105: Retrieve the WMI objects.
Line 107-138: Match the disk drive letter to the SCSI Lun information.
Sample usage
Output 1 will show you an example of the results you can get when you run the Get-DiskScsiLun function.
Computer DeviceID SCSIBus SCSIPort SCSITargetId SCSILogicalUnit -------- -------- ------- -------- ------------ --------------- server001 C: 0 2 5 1 server001 D: 0 0 4 0 server001 E: 0 2 4 2 server001 F: 0 1 5 3 server001 G: 0 2 4 4 server001 H: 0 1 5 13 server001 I: 0 1 5 5 server001 J: 0 2 5 6 server001 K: 0 2 4 7 server001 L: 0 2 5 8 server001 M: 0 1 4 9 server001 N: 0 1 4 10 server001 O: 0 2 5 11 server001 P: 0 2 5 12
Output 1. Sample output of the Get-DiskScsiLun function.
Update 17-1-2013: I modified the Get-DiskScsiLun function to not only retrieve the SCSILogicalUnit but also SCSIBus, SCSIPort and SCSITargetId.

This don’t work for mount points though
Hi Kelvin, you are right that this doesn’t work for mount points. It is not easy find a solution for mount points. I am still searching for it.
My output shows all LUN#’s as ’0′, this comes from $Win32_DiskDrive, all the LUN #’s on a VMware LSI Logic SAS.
PS C:\> $Win32_DiskDrive | select Name,SCSILogicalUnit | ft -AutoSize
Name SCSILogicalUnit
—- —————
\\.\PHYSICALDRIVE1 0
\\.\PHYSICALDRIVE0 0
That is pretty normal since LSI-Logic Controllers are incrementing the target number.
So your second RAID-Volume shows up as Target1:Lun0
3rd ist Target2:Lun0 etc.
in SCSI Targets are counted starting with 0
Thanks Thomas for making this clear. To make the Get-DiskScsiLun function also useful for LSI-Logic controllers did I modify the function to also retrieve the SCSIBus, SCSIPort and SCSITargetId.
Pingback: Enumerate DiskLuns | digital36 Blog-sphere