I am trying to get these 3 counters thru PowerShell, could you help? Something like below:
Hostname1 : CPU% : 75%
Hostname1 : MEM% : 55%
Hostname1 : Disk1 % : 15%
Hostname1 : Disk2 % : 10%
Hostname1 : Disk3 % : 13%
Hostname1 : Disk4 % : 12%
Hostname2 : CPU% : 75%
Hostname2 : MEM% : 55%
Hostname2 : Disk1 % : 11%
Hostname2 : Disk2 % : 15%
Hostname2 : Disk3 % : 15%
Note: I could not find a counter for %used/memory so I am not going thru performance counters.
Likely your easiest method is using WMI. The below is a script I wrote up for you to demonstrate the ability.
You would need to work on the formatting and I left out disk stats - so some work required.
# Lets import our list of computers
$computers = get-Content .\computer-list.txt
# computer-list.txt is your hostnames each on a new line
# Lets create our variables
$HostInfo = #()
# Lets loop through our computer list from computers
foreach ($computer in $computers) {
# Lets get our stats
# Lets create a re-usable WMI method for CPU stats
$ProcessorStats = Get-WmiObject win32_processor -computer $computer
$ComputerCpu = $ProcessorStats.LoadPercentage
# Lets create a re-usable WMI method for memory stats
$OperatingSystem = Get-WmiObject win32_OperatingSystem -computer $computer
# Lets grab the free memory
$FreeMemory = $OperatingSystem.FreePhysicalMemory
# Lets grab the total memory
$TotalMemory = $OperatingSystem.TotalVisibleMemorySize
# Lets do some math for percent
$MemoryUsed = ($FreeMemory/ $TotalMemory) * 100
$PercentMemoryUsed = "{0:N2}" -f $MemoryUsed
# Lets throw them into an object for outputting
$objHostInfo = New-Object System.Object
$objHostInfo | Add-Member -MemberType NoteProperty -Name Name -Value $computer
$objHostInfo | Add-Member -MemberType NoteProperty -Name CPULoadPercent -Value $ComputerCpu
$objHostInfo | Add-Member -MemberType NoteProperty -Name MemoryUsedPercent -Value $PercentMemoryUsed
# Lets dump our info into an array
$HostInfo += $objHostInfo
}
# Lets output to the console
$HostInfo
This works:
$system = Get-WmiObject win32_OperatingSystem
$totalPhysicalMem = $system.TotalVisibleMemorySize
$freePhysicalMem = $system.FreePhysicalMemory
$usedPhysicalMem = $totalPhysicalMem - $freePhysicalMem
$usedPhysicalMemPct = [math]::Round(($usedPhysicalMem / $totalPhysicalMem) * 100,1)
$driveLetters = Get-WmiObject Win32_Volume | select DriveLetter
foreach ($driveLetter in $driveLetters)
{
$drive = Get-WmiObject Win32_Volume | where {$_.DriveLetter -eq $driveLetter.DriveLetter}
$usedDiskSpace = $drive.Capacity - $drive.FreeSpace
$usedDiskSpacePct = [math]::Round(($usedDiskSpace / $drive.Capacity) * 100,1)
}
Related
I need to enumerate all firewall rules on windows 10 using PowerShell. I switched to PowerShell from netsh because some built-in rules were getting funny names like #{microsoft.windows.shellexperiencehost_10.0.17134.1_neutral_neutral_cw5n1h2txyewy?ms-resource://microsoft.windows.shellexperiencehost/resources/pkgdisplayname} which I was unable to manage with netsh. Switching to PowerShell shows that the real name was a UID and fixed my problem but the code is really slow to run:
PS C:\Users\vagrant\Desktop> Measure-Command {.\ps-slow.ps1 show}
Seconds : 48
...
In contrast to Measure-Command {show-netfirewallrule}:
...
Milliseconds : 644
And netsh:
PS C:\Users\vagrant\Desktop> Measure-Command { netsh advfirewall firewall show rule all verbose}
...
TotalSeconds : 1.0588127
By commenting out the Get-NetFirewall*Filter part of the script it runs at full speed but of course is missing all the data I want. The idea is to collect detailed info on all firewall rules and then output the lot as JSON.
Does anyone have an idea how to optimize this? I'm a PowerShell noob so I'm hoping I missed something obvious. The complete script is:
Show-NetFirewallRule | `
Where-Object { $_.cimclass.toString() -eq "root/standardcimv2:MSFT_NetFirewallRule" } | `
ForEach-Object { `
$af = $_ | Get-NetFirewallAddressFilter | Select-Object -First 1; # Assumes only one filter
$appf = $_ | Get-NetFirewallApplicationFilter | Select-Object -First 1; # Assumes only one filter
$pf = $_ | Get-NetFirewallPortFilter | Select-Object -First 1; # Assumes only one filter
$if = $_ | Get-NetFirewallInterfaceTypeFilter | Select-Object -First 1; # Assumes only one filter
New-Object -Type PSCustomObject -Property #{
Name = $_.Name
DisplayName = $_.DisplayName
Description = $_.Description
Enabled = $_.Enabled.toString()
Action = $_.Action.toString()
Direction = $_.Direction.toString()
EdgeTraversalPolicy = $_.EdgeTraversalPolicy.toString()
Profile = $_.Profile.toString()
DisplayGroup = $_.DisplayGroup
# Address Filter
LocalAddress = $af.LocalAddress
RemoteAddress = $af.RemoteAddress
LocalIp = $af.LocalIp
RemoteIp = $af.RemoteIp
# Port Filter
LocalPort = $pf.LocalPort
RemotePort = $pf.RemotePort
Protocol = $pf.Protocol
IcmpType = $pf.IcmpType
# Application Filter
Program = $appf.Program
# Interface Filter
InterfaceType = $if.InterfaceType.toString()
}
} | Convertto-json
This approach is faster, so, maybe a different approach for you to get the same information.
param
(
[switch]$Local,
[switch]$GPO
)
# If no switches are set the script will default to local firewall rules
if (!($Local) -and !($Gpo))
{ $Local = $true }
$RegistryKeys = #()
if ($Local) {$RegistryKeys += 'Registry::HKLM\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules'}
if ($GPO) {$RegistryKeys += 'Registry::HKLM\Software\Policies\Microsoft\WindowsFirewall\FirewallRules'}
Foreach ($Key in $RegistryKeys)
{
if (Test-Path -Path $Key)
{
(Get-ItemProperty -Path $Key).PSObject.Members |
Where-Object {
(#('PSPath','PSParentPath','PSChildName') -notcontains $_.Name) -and
($_.MemberType -eq 'NoteProperty') -and
($_.TypeNameOfValue -eq 'System.String')} |
ForEach-Object {
# Prepare hashtable
$HashProps = #{
NameOfRule = $_.Name
RuleVersion = ($_.Value -split '\|')[0]
Action = $null
Active = $null
Dir = $null
Protocol = $null
LPort = $null
App = $null
Name = $null
Desc = $null
EmbedCtxt = $null
Profile = $null
RA4 = $null
RA6 = $null
Svc = $null
RPort = $null
ICMP6 = $null
Edge = $null
LA4 = $null
LA6 = $null
ICMP4 = $null
LPort2_10 = $null
RPort2_10 = $null
}
# Determine if this is a local or a group policy rule and display this in the hashtable
if ($Key -match 'HKLM\\System\\CurrentControlSet')
{ $HashProps.RuleType = 'Local' }
else
{ $HashProps.RuleType = 'GPO' }
# Iterate through the value of the registry key and fill PSObject with the relevant data
ForEach ($FireWallRule in ($_.Value -split '\|'))
{
switch (($FireWallRule -split '=')[0])
{
'Action' {$HashProps.Action = ($FireWallRule -split '=')[1]}
'Active' {$HashProps.Active = ($FireWallRule -split '=')[1]}
'Dir' {$HashProps.Dir = ($FireWallRule -split '=')[1]}
'Protocol' {$HashProps.Protocol = ($FireWallRule -split '=')[1]}
'LPort' {$HashProps.LPort = ($FireWallRule -split '=')[1]}
'App' {$HashProps.App = ($FireWallRule -split '=')[1]}
'Name' {$HashProps.Name = ($FireWallRule -split '=')[1]}
'Desc' {$HashProps.Desc = ($FireWallRule -split '=')[1]}
'EmbedCtxt' {$HashProps.EmbedCtxt = ($FireWallRule -split '=')[1]}
'Profile' {$HashProps.Profile = ($FireWallRule -split '=')[1]}
'RA4' {[array]$HashProps.RA4 += ($FireWallRule -split '=')[1]}
'RA6' {[array]$HashProps.RA6 += ($FireWallRule -split '=')[1]}
'Svc' {$HashProps.Svc = ($FireWallRule -split '=')[1]}
'RPort' {$HashProps.RPort = ($FireWallRule -split '=')[1]}
'ICMP6' {$HashProps.ICMP6 = ($FireWallRule -split '=')[1]}
'Edge' {$HashProps.Edge = ($FireWallRule -split '=')[1]}
'LA4' {[array]$HashProps.LA4 += ($FireWallRule -split '=')[1]}
'LA6' {[array]$HashProps.LA6 += ($FireWallRule -split '=')[1]}
'ICMP4' {$HashProps.ICMP4 = ($FireWallRule -split '=')[1]}
'LPort2_10' {$HashProps.LPort2_10 = ($FireWallRule -split '=')[1]}
'RPort2_10' {$HashProps.RPort2_10 = ($FireWallRule -split '=')[1]}
Default {}
}
}
# Create and output object using the properties defined in the hashtable
New-Object -TypeName 'PSCustomObject' -Property $HashProps
}
}
}
# Partial results
Action : Allow
LPort2_10 :
RuleType : Local
LPort : 135
Edge :
LA6 :
Dir : In
Desc : #icsvc.dll,-710
ICMP4 :
RA4 :
Name : #icsvc.dll,-709
LA4 :
App : %SystemRoot%\system32\svchost.exe
ICMP6 :
Protocol : 6
RuleVersion : v2.0
NameOfRule : vm-monitoring-dcom
RPort :
Svc : RpcSs
RA6 :
Profile :
EmbedCtxt : #icsvc.dll,-700
RPort2_10 :
Active : FALSE
Ok thanks heaps for everyone who posted. The original problem was that netsh leaves unresolved names like:
#{Microsoft.Todos_1.41.12842.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Todos/Resources/app_name_ms_todo}
#{Microsoft.Todos_1.41.12842.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Todos/Resources/app_name_ms_todo}
In its output that can only be resolved by PowerShell, using the original script. The problem with this approach is that this is very slow (minutes).
Suggestions on this thread and from colleagues were:
Use PS batching (made things slower - suggesting WMI bottleneck)
Read the registry directly (mostly works, but data is left unresolved in different ways and would require slow registry scans to resolve - eg #FirewallAPI.dll,-25427 to whatever resource that references)
Use the COM API New-Object -ComObject HNetCfg.FwPolicy (has the same output problems as netsh)
Adjust use of pipelines/object creation (no measurable impact)
In summary, the optimization I want is impossible without sacrificing the data that I want. I'm going to attempt to use the faster COM API/netsh most of the time but switch to using the powershell API when there is no choice (when unresolved names force us to)
Does Get-NetFirewallRule give you what you want?
$MyRules = Get-NetFirewallRule
foreach ($rule in $MyRules) {
[the rest of your code]
}
I don't think this is well understood, but the get-netfirewall*filter commands are meant to do things faster. Just compare the first pipeline to the second pipeline. It's like using the -filter option in other commands like get-childitem or get-wmiobject. I don't think even the writers of the online help understand this. It's like powershell is only 80% documented.
Get-NetFirewallRule |
Get-NetFirewallPortFilter |
Where LocalPort -eq 3389 | Get-NetFirewallRule |
Set-NetFirewallRule -RemoteAddress 192.168.1.1 -WhatIf
Get-NetFirewallPortFilter |
Where LocalPort -eq 3389 | Get-NetFirewallRule |
Set-NetFirewallRule -RemoteAddress 192.168.1.1 -WhatIf
I have basic knowledge of PowerShell and I have been given a project that needs me to create a PowerShell script that gets all the computers on the domain in active directory and gather the free space/used space of each computer.
This is what I use in order to get servers with low disk space:
Import-Module ActiveDirectory
$Servers = Get-ADcomputer -Filter {OperatingSystem -like "*Server*"} -Properties Name, OperatingSystem -SearchBase "DC=yourDN,DC=local" | Select Name
$diskReport = Foreach($Server in $Servers)
{
#$Status = "Offline"
$Name = $Server.Name
#Make sure server is online
if(Test-Connection -ComputerName $Name -ErrorAction SilentlyContinue)
{
#Get only 10%
Get-WMIObject win32_logicaldisk -ComputerName $Name -Filter "DriveType=3" -ErrorAction SilentlyContinue | Where-Object { ($_.freespace/$_.size) -le '0.1'}
}
else
{
#Server is offline
}
}
$lowservers = $diskreport | Select-Object #{Label = "Server Name";Expression = {$_.SystemName}},
#{Label = "Drive Letter";Expression = {$_.DeviceID}},
#{Label = "Total Capacity (GB)";Expression = {"{0:N1}" -f( $_.Size / 1gb)}},
#{Label = "Free Space (GB)";Expression = {"{0:N1}" -f( $_.Freespace / 1gb ) }},
#{Label = 'Free Space (%)'; Expression = {"{0:P0}" -f ($_.freespace/$_.size)}}
This will first pull all your objects using Get-ADComputer. Then it just does a simple foreach to put everything into $diskReport. The $lowservers is just to clean it up a bit.
You can do whatever you want with $lowservers. I have mine on a scheduled task to run every Monday and Friday. Then send out an email if it finds something low.
this code almost works, it maps VWare VMDK to windows drives. The code is not mine.
Among other info it will return "DD-SERV-01_15.vmdk for VM MAIN is Drive letter G:"
The script will prompt for credentials and proceeds to map however something goes wrong and only the last VM / Drive is is saved as output - I was hoping someone could take a look and update / fix the code so that it saves all output please?
Thanks.
#Get VMware Disk Usage
# Created by Hugo Peeters
# http://www.peetersonline.nl
# VARIABLES
$Decimals = 1
$VCServer = "SERVERNAME"
# SCRIPT
# Connect to VC
Write-Progress "Gathering Information" "Connecting to Virtual Center" -Id 0
$VC = Connect-VIServer $VCServer
# Create Output Collection
$myCol = #()
# List Datastores (Datastore Name)
Write-Progress "Gathering Information" "Listing Datastores" -Id 0
$Datastores = Get-Datastore | Sort Name
# List vms
Write-Progress "Gathering Information" "Listing VMs and Disk Files" -Id 0
$VMSummaries = #()
ForEach ($vm in (Get-VM))
{
$VMView = $VM | Get-View
ForEach ($VirtualSCSIController in ($VMView.Config.Hardware.Device | Where {$_.DeviceInfo.Label -match "SCSI Controller"}))
{
ForEach ($VirtualDiskDevice in ($VMView.Config.Hardware.Device | Where {$_.ControllerKey -eq $VirtualSCSIController.Key}))
{
$VMSummary = "" | Select VM, HostName, PowerState, DiskFile, DiskName, DiskSize, SCSIController, SCSITarget
$VMSummary.VM = $VM.Name
$VMSummary.HostName = $VMView.Guest.HostName
$VMSummary.PowerState = $VM.PowerState
$VMSummary.DiskFile = $VirtualDiskDevice.Backing.FileName
$VMSummary.DiskName = $VirtualDiskDevice.DeviceInfo.Label
$VMSummary.DiskSize = $VirtualDiskDevice.CapacityInKB * 1KB
$VMSummary.SCSIController = $VirtualSCSIController.BusNumber
$VMSummary.SCSITarget = $VirtualDiskDevice.UnitNumber
$VMSummaries += $VMSummary
}
}
Clear-Variable VMView -ErrorAction SilentlyContinue
}
# Loop through Datastores
ForEach ($Datastore in $Datastores)
{
# List vmdk files in datastore (vmdk Name)
Write-Progress "Gathering Information" ("Processing Datastore {0}" -f $Datastore.Name) -Id 0
$DSView = $Datastore | Get-View
$fileQueryFlags = New-Object VMware.Vim.FileQueryFlags
$fileQueryFlags.FileSize = $true
$fileQueryFlags.FileType = $true
$fileQueryFlags.Modification = $true
$searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpec.details = $fileQueryFlags
$searchSpec.sortFoldersFirst = $true
$dsBrowser = Get-View $DSView.browser
$rootPath = "["+$DSView.summary.Name+"]"
$searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec)
ForEach ($result in $searchResult)
{
ForEach ($vmdk in ($result.File | ?{$_.Path -like "*.vmdk"} | Sort Path))
{
Write-Progress "Gathering Information" ("Processing VMDK {0}" -f $vmdk.Path) -Id 1
Write-Host "=============================================================================="
# Find vm using the vmdk (VM Name)
$VMRef = ($VMSummaries | ?{$_.DiskFile -match $Datastore.Name -and $_.DiskFile -match $vmdk.Path})
"VMDK {0} belongs to VM {1}" -f $vmdk.Path, $VMRef.VM
If ($VMRef.Powerstate -eq "PoweredOn")
{
Write-Host "VM is powered on" -ForegroundColor "yellow"
$Partitions = Get-WmiObject -Class Win32_DiskPartition -ComputerName $VMRef.HostName
If ($?)
{
$Disks = Get-WmiObject -Class Win32_DiskDrive -ComputerName $VMRef.HostName
$LogicalDisks = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $VMRef.HostName
$DiskToPartition = Get-WmiObject -Class Win32_DiskDriveToDiskPartition -ComputerName $VMRef.HostName
$LogicalDiskToPartition = Get-WmiObject -Class Win32_LogicalDiskToPartition -ComputerName $VMRef.HostName
Write-Host "Read partition and disk information" -ForegroundColor "yellow"
# Match disk based on SCSI ID's
$DiskMatch = $Disks | ?{($_.SCSIPort - 1) -eq $VMRef.SCSIController -and $_.SCSITargetID -eq $VMRef.SCSITarget}
If ($DiskMatch -eq $null){Write-Warning "NO MATCHES!"}
Else
{
Write-Host "Found match:" -ForegroundColor "yellow"
$DiskMatch
# Find the Partition(s) on this disk
$PartitionsOnDisk = ($DiskToPartition | ?{$_.Antecedent -eq $DiskMatch.__PATH})
If ($PartitionsOnDisk -eq $null){Write-Warning "NO PARTITIONS!"}
Else
{
ForEach ($PartitionOnDisk in $PartitionsOnDisk)
{
Write-Host "Disk contains partition" -ForegroundColor "yellow"
$PartitionOnDisk.Dependent
$PartitionMatches = $Partitions | ?{$_.__PATH -eq $PartitionOnDisk.Dependent}
ForEach ($PartitionMatch in $PartitionMatches)
{
$LogicalDiskRefs = $LogicalDiskToPartition | ?{$_.Antecedent -eq $PartitionMatch.__PATH}
If ($LogicalDiskRefs -eq $null)
{
Write-Warning "NO LOGICAL DISKS!"
}
Else
{
ForEach ($LogicalDiskRef in $LogicalDiskRefs)
{
$LogicalDiskMatches = $LogicalDisks | ?{$_.__PATH -eq $LogicalDiskRef.Dependent}
ForEach ($LogicalDiskMatch in $LogicalDiskMatches)
{
Write-Host "Matching Logical Disk:" -ForegroundColor "yellow"
$LogicalDiskMatch
# Create Output Object
$myObj = "" | Select Datastore, DSSizeGB, DSFreeGB, DSPercentFree, DiskFile, VM, HardDisk, DriveLetter, DiskSizeGB, DiskFreeGB, PercFree
# List datastore name
$myObj.Datastore = $Datastore.Name
# Determine datastore size in GB
$myObj.DSSizeGB = [Math]::Round(($Datastore.CapacityMB * 1MB / 1GB),$Decimals)
$myObj.DSFreeGB = [Math]::Round(($Datastore.FreeSpaceMB * 1MB / 1GB),$Decimals)
# Determine datastore free space (DS%Free)
$myObj.DSPercentFree = [Math]::Round((100*($Datastore.FreeSpaceMB/$Datastore.CapacityMB)),$Decimals)
# List disk file name
$myObj.DiskFile = $vmdk.Path
# List VM Name
$myObj.VM = $VMRef.VM
# Determine virtual hard disk / logical drive
$myObj.HardDisk = $VMRef.DiskName
# Report driveletter
$myObj.DriveLetter = $LogicalDiskMatch.DeviceID
# Report Size
$myObj.DiskSizeGB = [Math]::Round(($LogicalDiskMatch.Size / 1GB),$Decimals)
# Report Free Space
$myObj.DiskFreeGB = [Math]::Round(($LogicalDiskMatch.FreeSpace / 1GB),$Decimals)
# Calculate Percentage free space
$myObj.PercFree = [Math]::Round((100 * ([int]($LogicalDiskMatch.FreeSpace / 1MB) / [int]($LogicalDiskMatch.Size / 1MB))),$Decimals)
Write-Host "RESULT:" -ForegroundColor "yellow"
$myObj
# Add output object to output collection
$myCol += $myObj
}
Clear-Variable LogicalDiskMatches -ErrorAction SilentlyContinue
}
}
Clear-Variable LogicalDiskRefs -ErrorAction SilentlyContinue
}
Clear-Variable PartitionMatches -ErrorAction SilentlyContinue
}
}
Clear-Variable PartitionsOnDisk -ErrorAction SilentlyContinue
}
Clear-Variable DiskMatch -ErrorAction SilentlyContinue
Clear-Variable Disks -ErrorAction SilentlyContinue
Clear-Variable LogicalDisks -ErrorAction SilentlyContinue
Clear-Variable DiskToPartition -ErrorAction SilentlyContinue
Clear-Variable LogicalDiskToPartition -ErrorAction SilentlyContinue
}
Clear-Variable Partitions -ErrorAction SilentlyContinue
}
Else
{
Write-Host "VM is powered off" -ForegroundColor "yellow"
}
Clear-Variable VMRef -ErrorAction SilentlyContinue
Write-Progress "Gathering Information" ("Processing VMDK {0}" -f $vmdk.Path) -Id 1 -Completed
}
}
}
# Disconnect from VC
Disconnect-VIServer -Confirm:$False
# OUTPUT
Write-Host "==================================================="
Write-Host "==================================================="
$TotalDSFree = ($myCol | Select Datastore, DSFreeGB -Unique | Measure-Object DSFreeGB -Sum).Sum
$TotalDSSize = ($myCol | Select Datastore, DSSizeGB -Unique | Measure-Object DSSizeGB -Sum).Sum
$AverageDSFree = [Math]::Round(100 * ($TotalDSFree / $TotalDSSize),$Decimals)
$AverageDiskFree = [Math]::Round(100 * (($myCol | Measure-Object DiskFreeGB -Sum).Sum / ($myCol | Measure-Object DiskSizeGB -Sum).Sum),$Decimals)
Write-Host "Total DS Free: $TotalDSFree"
Write-Host "Total DS Size: $TotalDSSize"
Write-Host "Average DS Free Percentage: $AverageDSFree"
Write-Host "Average Disk Free Percentage: $AverageDiskFree"
$myCol | Export-Csv -NoTypeInformation 'C:\TEMP\VMwareDiskUsage.csv'
Try adding the -Append parameter to your export-csv, so it does not overwrite the last entry:
$myCol | Export-Csv -Append -NoTypeInformation 'C:\TEMP\VMwareDiskUsage.csv'
I have this code that generates a list of all the shares and the size however can not generate a txt with this information or the shared location
$servers = #("servername")
$sizes = #()
foreach($server in $servers) {
write-host "Server: $server"
(gwmi -class Win32_Share -ComputerName $server -filter "Type = 0" |
% {
write-host " share: $($_.Name)"
$s = gci \\$server\$($_.Name) -recurse -force | Measure-Object -Property length -Sum
New-Object PSObject -property #{Name=$_.Name; Server=$server; TotalSize=$s.Sum }
})
}
And this not only shows me the size and generates txt size and can generate txt
Get-WmiObject Win32_share -computer server01 | FT "server01", path, name > ServerShares.txt
Get-WmiObject Win32_share -computer server02 | FT "server02", path, name >> ServerShares.txt
Someone could help me to create only one that does everything
In your New-Object you just need to add additional properties to get the information you want:
If you're not running PowerShell v3, remove [Ordered]
$servers = #("servername")
$sizes = #()
foreach($server in $servers)
{
write-host "Server: $server"
# Get all shares
$shares = Get-WmiObject -class Win32_Share -ComputerName $server -filter "Type = 0"
# go through each share
foreach($share in $shares)
{
write-host " share: $($share.Name)"
# Get size of share
$size = Get-ChildItem -Path "\\$server\$($_.Name)" -recurse -force | Measure-Object -Property length -Sum
# Create a new object to store information
New-Object PSObject -property ([ordered]#{
# Name of share
Name = $share.Name
# Share path
Path = $share.path
# What server share is on
Server = $server
# Total size of share
TotalSize = $size.Sum
# Change this path to where you want the file to be saved to
}) | Export-Csv -Path C:\ShareDetails.csv -NoTypeInformation -Append
}
}
I made a small revision to #Bluecakes response in order to use COM instead of .NET to capture the size information. This overcomes the path-length issues.
# Get size of share
# $size = Get-ChildItem -Path "$($share.Name)" -recurse -force | Measure-Object -Property length -Sum
$objFSO = New-Object -com Scripting.FileSystemObject
$size = "{0:N2}" -f (($objFSO.GetFolder("$($share.Name)").Size) / 1MB)
Then you also need to remove ".sum"
# Total size of share
TotalSize = $size
I am trying to format a PSObject related to a question a few days back. My object looks like this:
New-Object PSObject -Property #{
"Version"= $winVersion.Caption
"Processor Name" = $processorInfo.Name
"Processor Manufacturer" = $processorInfo.Manufacturer
"Processor Max Clock Speed" = $processorInfo.MaxClockSpeed
} |format-list
The above gives the following output:
Processor Manufacturer : GenuineIntel
Processor Max Clock Speed : 2201
Version : Microsoft Windows 8 Pro
Processor Name : Intel(R) Core(TM) i7-2670QM CPU # 2.20GHz
However, this:
New-Object PSObject -Property #{
"Windows Version"= $winVersion.Caption
"Processor Name" = $processorInfo.Name
"Processor Manufacturer" = $processorInfo.Manufacturer
"Processor Max Clock Speed" = $processorInfo.MaxClockSpeed
} |format-list
gives the following output:
Processor Manufacturer : GenuineIntel
Processor Max Clock Speed : 2201
Processor Name : Intel(R) Core(TM) i7-2670QM CPU # 2.20GHz
Windows Version : Microsoft Windows 8 Pro
Not really a big deal, but I wonder why the formatting changes? It does not seem to be alphabetical in any way. Furthermore, I tried sorting the object with Sort-Object (from A-Z) but to no avail. Is it String related?
The order of a hashtable can't be predicted (in PowerShell V3.0 you can user the [ordered] accelerator to make an hashtable ordered), but in V2.0 you need to build your custom object like this to preserve properties order:
$o = New-Object PSObject
$o | add-member Noteproperty "Version" $winVersion.Caption
$o | add-member Noteproperty "Processor Name" $processorInfo.Name
$o | add-member Noteproperty "Processor Manufacturer" $processorInfo.Manufacturer
$o | add-member Noteproperty "Processor Max Clock Speed" $processorInfo.MaxClockSpeed
$o | format-list
You can still add a custom method to your object to provide the format you want, for example:
$test = New-Object PSObject -Property #{
"Processor Manufacturer"="GenuineIntel"
"Processor Max Clock Speed" = "2201"
"Version"="Microsoft Windows 8 Pro"
}
Add-Member -MemberType ScriptMethod -Name "show" -Value {echo $this.version;echo $this."processor manufacturer";echo $this."Processor Max Clock Speed"} -inputObject $test
$test.show()