I still have not decided, is it really overkill or just very nice? Or is it not solving the issue at all or is actually quite useful? I got a mail from an internal mailing list about getting some quick feedback on code that was written to retrieve disk free space from a single or several machines. The actual question was somewhat directed towards a one-liner, but why would I write something that is not reusable? So while not exactly an answer to the question, but using some simple tricks I think the script itself is pretty nice and actually uses some intelligence to retrieve information, fixing some stuff with objects etc. Ah well, just enjoy and use if you can! It retrieves the disk free space in GB and in %.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
function Get-DiskspaceReport { # Sertup cmdlet and our default output type [CmdletBinding(DefaultParameterSetName='Default')] [OutputType([System.Management.Automation.PSCustomObject],ParameterSetName='Default')] PARAM( # Four parameter sets 1 = no creds, 2 = pscreds, 3 = cleartext password, 4 = secure string password # accept computer name and drive names, drive names and computer names are validated using very basic validation [Parameter(Position=0,Mandatory=$true,HelpMessage='Name of host to connect to',ParameterSetName='Default',ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$ComputerName, [Parameter(Position=1,Mandatory=$false,HelpMessage='Which drive to scan if not system drive',ParameterSetName='Default')] [ValidatePattern('^[a-zA-Z]{1}:')] [ValidateNotNullOrEmpty()] [string[]]$Drive = $null, [Parameter(Position=2,Mandatory=$false,HelpMessage='Credentials used to connect to remote system',ParameterSetName='PSCredential')] [System.Management.Automation.PSCredential]$Credential, [Parameter(Position=2,Mandatory=$false,HelpMessage='Username used to connect to remote system',ParameterSetName='Cleartext')] [Parameter(Position=2,Mandatory=$false,HelpMessage='Username used to connect to remote system',ParameterSetName='SecureString')] [string]$Username, [Parameter(Position=3,Mandatory=$false,HelpMessage='Cleartext password (bad!) used to connect to remote system',ParameterSetName='Cleartext')] [string]$CleartextPassword, [Parameter(Position=3,Mandatory=$false,HelpMessage='SecureString password used to connect to remote system',ParameterSetName='SecureString')] [SecureString]$Password ) BEGIN { try { # If specified construct credentials to use switch($PSCmdlet.ParameterSetName) { 'PSCredential' { $remoteCred = $Credential } 'SecureString' { $remoteCred = New-Object System.Management.Automation.PsCredential($Username, $Password) } 'Cleartext' { $remoteCred = New-Object System.Management.Automation.PsCredential($Username, (ConvertTo-SecureString $CleartextPassword -AsPlainText -Force)) } default { $remoteCred = $null } } } catch { # Above should really not fail, but just to be sure throw "An error occured while initializing credentials: $($_.Exception.Message)" } } PROCESS { # if we got an array of computer names (ie not pipe) foreach($computer in $computerName) { try { # Open connection to remote computer, use credentials if availiable $cimConnection = New-CIMSession -ComputerName $computer -Credential $remoteCred # Get some data (ComputerName and system drive, computer name must be queries as we could use alias to connect..) $systemData = Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $cimConnection # Which drives to check, if specified just query those otherwise query system drive if ($Drive -eq $null) { $Drive = @($systemData.SystemDrive)} # Retrieve logical disk information and then tweak the output object a little Get-CimInstance -ClassName Win32_LogicalDisk -CimSession $cimConnection | Where-Object { $_.DeviceID -in $Drive } | Select-Object @{Name='ComputerName';Expression={$systemData.CSName}}, @{Name='DriveLetter';Expression={$_.DeviceID}}, @{Name='SizeFree';Expression={[Math]::Round($_.FreeSpace/1GB,2)}}, @{Name='PercentFree';Expression={[Math]::Round(($_.FreeSpace/$_.Size)*100,2)}} | ForEach-Object { $_.PSObject.TypeNames.Insert(0,'System.Management.Automation.PSCustomObject#DiskSpaceObject'); Write-Output $_ } | Write-Output #Close the session Remove-CimSession $cimConnection } catch { #Lazy catch, get all errors to the error stream and continue loop Write-Error "An error occured while processing '$computer': $($_.Exception.Message)" } } } } |