Script not getting drive letter and volume

Hello,
I am trying to gather some disk information. Im trying to make it easier to submit the information to the storage team when we have to get Windows san disks extended.

This script does not get the letter or volume name, anyone point out why? It outputs the hostname and drive number, but the next 2 fields are blank.

$computer = Get-WmiObject -Class Win32_ComputerSystem
$hostname = $computer.Name

$disks = Get-WmiObject -Class Win32_DiskDrive
foreach ($disk in $disks) {
    $index = $disk.Index
    $partitions = Get-WmiObject -Class Win32_DiskPartition -Filter "DiskIndex = $index"
 
    foreach ($partition in $partitions) {
        $letter = (Get-WmiObject -Class Win32_LogicalDisk | Select-Object {$_.DeviceID})
        $volumename = (Get-WmiObject -Class Win32_LogicalDisk | Select-Object {$_.VolumeName})
        #$label = (Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='$($partition.DeviceID)'" ).VolumeName
        Write-Host "Hostname: $hostname" -ForegroundColor Green
        Write-Host "Drive Index: $index" -ForegroundColor Green
        Write-Host "Drive Letter: $letter" -ForegroundColor Green
        Write-Host "Drive Label: $volumename" -ForegroundColor Green
    }
}

This is really only the first part, because once I have this information, I need to run “powermt display dev=all” to be able to get the WWN of each disk.

The output of the powermt command looks like this:

Pseudo name=harddisk24
Symmetrix ID=00046546456
Logical device ID=00000222
Device WWN=6000097563456467567565646
state=alive; policy=SymmOpt; queued-IOs=0
==============================================================================
--------------- Host ---------------   - Stor -  -- I/O Path --   -- Stats ---
###  HW Path               I/O Paths    Interf.  Mode     State   Q-IOs Errors
==============================================================================
   4 port4\path0\tgt1\lun24 c4t1d24    FA  8d:04 active   alive      0      0
   4 port4\path0\tgt0\lun24 c4t0d24    FA 10d:04 active   alive      0      0
   3 port3\path0\tgt1\lun24 c3t1d24    FA  9d:05 active   alive      0      0
   3 port3\path0\tgt0\lun24 c3t0d24    FA  7d:05 active   alive      0      0

So I need to correlate the Pseudo name=harddisk24 with Index number 24 from the first script output, and then grab the Device WWN.

But…I cant get the first script working :frowning:

Any help would be great, Thanks!

First of all: You should not use Get-WmiObject anymore as it is deprecated and can be replaced with its successor

Next …

It is unnecessary to query the same WMI class twice … AND when you select a particular property with Select-Object you don’t use the pipeline variable $_. Instead you simply provide the property name. But that’s not needed anyway.

So your code should look like this:

$computer = Get-WmiObject -Class Win32_ComputerSystem
$hostname = $computer.Name

$disks = Get-WmiObject -Class Win32_DiskDrive
foreach ($disk in $disks) {
    $index = $disk.Index
    $partitions = Get-WmiObject -Class Win32_DiskPartition -Filter "DiskIndex = $index"
 
    foreach ($partition in $partitions) {
        $LogicalDisk = Get-WmiObject -Class Win32_LogicalDisk

        Write-Host "Hostname: $hostname" -ForegroundColor Green
        Write-Host "Drive Index: $index" -ForegroundColor Green
        Write-Host "Drive Letter: $($LogicalDisk.DeviceID)" -ForegroundColor Green
        Write-Host "Drive Label: $($LogicalDisk.VolumeName)" -ForegroundColor Green
    }
}

BUT and it is a big but - the query for the logical disk inside your loop is completely unrelated to the partitions. When you have 3 partitions you get the same logical disks 3 times.

And you should not use Write-Host

Hello all,

Olaf - I reworked it taking your advice. Its better, but I still need some help I think. My output looks like this:

ComputerName	DiskNumber	DriveLetter	VolumeName	WWNN	WWPN	PSComputerName	RunspaceId	PSShowComputerName
ServerName	System.Collections.ArrayList	B:	Backup	20000025b59c0c13	20000025b59c0a13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	B:	Backup	20000025b59c0c13	20000025b59c0b13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	C:		20000025b59c0c13	20000025b59c0a13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	C:		20000025b59c0c13	20000025b59c0b13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	E:	Data	20000025b59c0c13	20000025b59c0a13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	E:	Data	20000025b59c0c13	20000025b59c0b13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	F:	Trace	20000025b59c0c13	20000025b59c0a13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE
ServerName	System.Collections.ArrayList	F:	Trace	20000025b59c0c13	20000025b59c0b13	ServerName	3742602a-50b5-4512-bc68-4e91d64039c9	TRUE

The Servername is correct, but i am not getting the drive number output. I get 2 of driveletter/volumename because its doing 1 per WWPN.

Any idea why I get that system.Collections.ArrayList for disk Number?

Here is my script:

Clear-Host
$remotecomputer = Read-Host -Prompt 'Please enter computer name to get disk information on'
$path = 'C:\temp\disk.xlsx'

Invoke-Command -ComputerName $remotecomputer -ScriptBlock {

    $computer = Get-CimInstance -Class Win32_ComputerSystem
    $hostname = $computer.Name
    $LogicalDisks = Get-CimInstance -Class Win32_LogicalDisk
      
    foreach ($disk in $logicaldisks) {
        $diskindex = Get-CimInstance -Class Win32_DiskDrive
        $ports = Get-InitiatorPort
        foreach ($p in $ports) {
   
            $resulthashtable = [ordered]@{
                ComputerName = $hostname
                DiskNumber   = $diskindex.index
                DriveLetter  = $disk.name
                VolumeName   = $disk.volumeName	
                WWNN         = $p.NodeAddress
                WWPN         = $p.PortAddress
            }
            [PSCustomObject]$resulthashtable 
        }
        
    } 
} | Export-Excel -Append -Path $path

Thanks!

I am actually unsure what ouput you expect. I’m afraid you have a missconception about the relations between the resturn values of the WMI clases you use.

Since $DiskNumber seems to be a collection - not a single element - you have to either join it into a single element to get the proper output or you need a loop. But if you have more than one unrelated array on one “level” there’s actually no meaningful way to combine those in one ouput.

$remotecomputer = Read-Host -Prompt 'Please enter computer name to get disk information on'

Invoke-Command -ComputerName $remotecomputer -ScriptBlock {
    $LogicalDisks = Get-CimInstance -Class Win32_LogicalDisk

    foreach ($disk in $logicaldisks) {
        $diskindex = Get-CimInstance -Class Win32_DiskDrive
        $ports = Get-InitiatorPort

        foreach ($p in $ports) {
            [PSCustomObject]@{
                ComputerName = $USING:remotecomputer
                DiskNumber   = $($diskindex.index) -join ', '
                DriveLetter  = $disk.name
                VolumeName   = $disk.volumeName	
                WWNN         = $p.NodeAddress
                WWPN         = $p.PortAddress
            }
        }
    } 
}

If you look in Disk Management on a windows server, it looks like the picture.

I am looking to gather for each disk listed, the hostname, the disk number I have circled, the drive letter and the volume names I have both circled.

I do not understand what you mean when you say disk number is a ‘collection’. It seems to be a number per disk to me.

The output from the script you modified looks like this when i export it to excel. Its putting all of the drive numbers on every line, close but not exactly what i am looking for.

I was trying to figure out how to do what you were explaining there as far as having more than 1 unrelated array per level.

Ideally I would like to output the partition # as well, but that was giving me the problem you just described. Most of the servers are standard, so they will all have hard disk 0 with 4 partitions, and hard disk 1-x having 1 partition each.

That get-initiator port command is not doing what I need it to either, but I have a different plan on getting that output.

Anyway, small steps lol.

Thanks for help!

oh I just realized another wrinkle to this mess, some of those disks are actually mount points…so like 10 or 15 of them all are mounted under the M volume. They are San disks, so each are an individual device with WWN etc.

Thanks!

From a WMI point of view these two informations are actually unrelated. If you want to match them you’d need to create a relation. … associate them … :wink:

It is a number per disk. But you query ALL disks for each individual logicaldisk again and again and again.

Here are some examples:

Nice, Thanks for that link Olaf. That is exactly what I was looking for, and no way I was coming up with that. Here is Ansgar Wiechers script, slightly modified:

Clear-Host
$remotecomputer = Read-Host -Prompt 'Please enter computer name to get disk information on'
$path = 'C:\temp\disk.xlsx'


Invoke-Command -ComputerName $remotecomputer -ScriptBlock {

Get-WmiObject Win32_DiskDrive | ForEach-Object {
  $disk = $_
  $partitions = "ASSOCIATORS OF " +
                "{Win32_DiskDrive.DeviceID='$($disk.DeviceID)'} " +
                "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
  Get-WmiObject -Query $partitions | ForEach-Object {
    $partition = $_
    $drives = "ASSOCIATORS OF " +
              "{Win32_DiskPartition.DeviceID='$($partition.DeviceID)'} " +
              "WHERE AssocClass = Win32_LogicalDiskToPartition"
    Get-WmiObject -Query $drives | ForEach-Object {
      [PSCustomObject][Ordered]@{
        Disk        = $disk.DeviceID
        DiskSize    = $disk.Size
        DiskModel   = $disk.Model
        Partition   = $partition.Name
        RawSize     = $partition.Size
        DriveLetter = $_.DeviceID
        VolumeName  = $_.VolumeName
        Size        = '{0:d} GB' -f [int]($_.Size / 1GB)
        FreeSpace   = '{0:d} GB' -f [int]($_.FreeSpace / 1GB)
      }
    }
  }
}
} | Export-Excel -Append -Path $path

Anyone know how I can convert the DiskSize and Rawsize fields to GB? I tried variations on what was used next to freespace, but was not able to get it converted right.

Thanks!

I would have prefered the solution suggested by js2010 since it uses Get-CimInstance instead of Get-WmiObject. But anyway … great that you’re satisfied now. :wink:

You divide it by 1GB?! :man_shrugging:t4: For example:

515396075520 / 1GB

That solution by js2010 might be better actually. The script I posted does not capture the mount points. To get the mount points, Get-Volume does it, but I have no idea how to add a Get-Volume into that script from Ansgar.

I may be able to modify js2010s though…Ill give that a try.

Thanks!