Search code examples
jsonpowershellremote-serverpowershell-remoting

Data collection from remote servers using powershell


I'm trying to get drive information from a list of windows 2008 - 2016 servers using powershell. I've got the code for getting the information but only from my local system, not remotely and not from a txt file of server names. Below is my code.

$Computers = @()

Function Get-DriveInfo {

  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 {
      New-Object -Type PSCustomObject -Property @{
        Disk        = $disk.DeviceID
        DiskSize    = '{0:d} GB' -f [int]($disk.Size / 1GB)
        DiskModel   = $disk.Model # Unique for Physical, VM, and SAN
        Partition   = $partition.Name
        RawSize     = '{0:d} GB' -f [int]($partition.Size / 1GB)
        DriveLetter = $_.DeviceID
        VolumeName  = $_.VolumeName
        Size        = '{0:d} GB' -f [int]($_.Size / 1GB)
        FreeSpace   = '{0:d} GB' -f [int]($_.FreeSpace / 1GB)
      }
    }
  }
}
}


$Computers += Get-DriveInfo $ComputerName
Write-Output $Computers

I also have a txt file that just lists server names

server1
server2
server3

I have 800+ servers to do this to. Once I have the data I am unsure as to what the best kind of file to dump the results to. I was told a json file might be a good idea to use but I have not used json before. Essentially I'm attempting to make a searchable object to allow me to display the results in this order:

DiskModel
Partition
FreeSpace
Size

Solution

  • If I'm understanding correctly, you want to be able to point this function at a list of computers and get return that shows the computer names it was run against. I've updated your function and will give you an example on how to use it.

    Create a CSV file with the column header set to "ComputerName". Fill the column with data however you like. Then do something like:

    $Computers = Import-CSV -Path .\Computers.csv
    Get-DriveInfo -Computername $Computers
    

    If you just want to test the waters with the updated function, try the following:

    get-driveinfo -Computername TestComputer1,TestComputer2
    

    Should get you the output you're looking for. As far as where to store it goes, that's really going to be up to your use case. You could just pipe to Export-CSV and make a spreadsheet. Or get really fancy and look into putting these values into an SQL database.

    Updated Function:

    Function Get-DriveInfo {
    [CmdletBinding()]
    Param (
        # Enter a ComputerName
        [Parameter(Mandatory=$false,
                   Position=0,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)] 
        [string[]]$ComputerName = "localhost")
    
    Foreach ($Computer in $ComputerName) {
    Invoke-Command -ComputerName $Computer -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 {
      $obj = New-Object -Type PSCustomObject -Property @{
        Disk        = $disk.DeviceID
        DiskSize    = '{0:d} GB' -f [int]($disk.Size / 1GB)
        DiskModel   = $disk.Model # Unique for Physical, VM, and SAN
        Partition   = $partition.Name
        RawSize     = '{0:d} GB' -f [int]($partition.Size / 1GB)
        DriveLetter = $_.DeviceID
        VolumeName  = $_.VolumeName
        Size        = '{0:d} GB' -f [int]($_.Size / 1GB)
        FreeSpace   = '{0:d} GB' -f [int]($_.FreeSpace / 1GB)
      }
    write-output $obj
    }
    }
    }
    }
    }
    }