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
Related
I'm using this Powershell script to retrieve info of remote servers from a central server.
In this case, there are about 150 servers on Active Directory:
$Servers = Get-ADComputer -Filter 'Name -like "...*"' | Select-Object -ExpandProperty Name
foreach ($computer in $Servers)
{
try
{
$ping = Test-Connection -ComputerName $computer -count 1 -ErrorAction Stop
$IP = ($ping.IPV4Address).IPAddressToString
$hardware = Get-CimInstance -Class Win32_ComputerSystem -ComputerName $computer -ErrorAction Stop
$totalMemory = (Get-CimInstance Win32_PhysicalMemory -ComputerName $computer | Measure-Object -Property capacity -Sum).sum /1gb
$os = Get-CimInstance -Class Win32_OperatingSystem -ComputerName $computer
$cpu = Get-CimInstance -Class Win32_processor -ComputerName $computer | Group-Object -Property Name |
Select-Object -Property Name,
#{Name = 'TotalSockets'; Expression = {$_.Count}},
#{Name = 'TotalCores'; Expression = {($_.Group | Measure-Object -Property NumberOfCores -Sum).Sum}},
#{Name = 'TotalLogicalProcessors'; Expression = {($_.Group | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum}}
#$disks = Get-WmiObject Win32_Volume -ComputerName $computer -Filter "DriveType='3'" | Sort-Object Name
# create new custom object to keep adding store information to it
$Result = New-Object -TypeName PSCustomObject -Property #{
ComputerName = $computer.ToUpper()
IPAddress = $IP
Manufacturer = $hardware.Manufacturer
Model = $hardware.Model
ADDescription = (Get-ADComputer -Identity $computer -Properties Description).Description -join ';'
ProductName = $os.Caption
OSVersion = $os.version
BuildNumber = $os.BuildNumber
OSArchitecture = $os.OSArchitecture
Domain = $hardware.Domain
'RAM (GB)' = $totalMemory
CPU = $cpu.Name
CPUTotalSockets = $cpu.TotalSockets
CPUTotalCores = $cpu.TotalCores
CPUTotalLogicalProcessors = $cpu.TotalLogicalProcessors
CPUVirtualizationFirmwareEnabled = (Get-CimInstance -Class Win32_processor -ComputerName $computer).VirtualizationFirmwareEnabled -join ','
}
# Column ordering, re-order if you like
<#$colOrder = 'ComputerName', 'IPAddress', 'Manufacturer', 'Model', 'ADDescription',
'ProductName', 'OSVersion', 'BuildNumber', 'OSArchitecture',
'Domain', 'RAM (GB)', 'CPU', 'CPUTotalSockets', 'CPUTotalCores',
'CPUTotalLogicalProcessors', 'CPUVirtualizationFirmwareEnabled'#>
# Return all your results
#$Result | Select-Object -Property $colOrder
$Result | Select-Object "ComputerName", "IPAddress", "Manufacturer", "Model", "ADDescription", "ProductName", "OSVersion", "BuildNumber",
"OSArchitecture", "RAM (GB)", "CPU", "CPUTotalSockets", "CPUTotalCores", "CPUTotalLogicalProcessors", "CPUVirtualizationFirmwareEnabled", "Domain" |
Export-Csv -Path "C:\SQL\Get-Inventory.csv" -Delimiter '|' -Append -NoTypeInformation
#$disks | Format-Table DriveLetter, Label, #{Name='Size(GB)'; Expression={[decimal]('{0:N0}' -f($_.Capacity/1gb))}}, #{Name='FreeSpace(GB)'; Expression={[decimal]('{0:N0}' -f($_.FreeSpace/1gb))}}
}
catch
{ Write-Output "--- $computer ---" $Error[0] `n | Add-Content -Path C:\SQL\UnreachableServers.txt }
}
The Powershell's process uses an average of 50/75 Mb of RAM. It's possible to reduce the RAM usage?
I accept any kind of advice given my little experience on Powershell :)
Thanks in advance.
Alessandro
I have been tasked to export all file sizes individually in all the shared folder exists on a computer except the system shares with ACL and Shared permissions.
Something like Treesize output with the Shared and ACL permissions.
I have tried the below code but it is not showing what I need in output.
Any help will be greatly appreciated.
function Get-ShareSize {
Param(
[String[]]$ComputerName = $env:computername
)
Begin{$objFldr = New-Object -com Scripting.FileSystemObject}
Process{
foreach($Computer in $ComputerName){
Get-WmiObject Win32_Share -ComputerName $Computer -Filter "not name like '%$'" | %{
$Path = $_.Path -replace 'C:',"\\$Computer\c$"
$Size = ($objFldr.GetFolder($Path).Size) / 1GB
New-Object PSObject -Property #{
Name = $_.Name
Path = $Path
Description = $_.Description
Size = $Size
}
}
}
}
}
Get-ShareSize -ComputerName localhost
Your code already looks quite good, but..
The way you use -Filter is wrong and also the part where you convert the $_.Path into a UNC path is not correct.
Apart from that, there is no need to us a Com object (Scripting.FileSystemObject) to get the actual size of the share.
Try this
function Get-ShareSize {
Param(
[String[]]$ComputerName = $env:computername
)
foreach($Computer in $ComputerName){
Get-WmiObject Win32_Share -ComputerName $Computer | Where-Object { $_.Name -notlike '*$' } | ForEach-Object {
# convert the Path into a UNC pathname
$UncPath = '\\{0}\{1}' -f $Computer, ($_.Path -replace '^([A-Z]):', '$1$')
# get the folder size
try {
$Size = (Get-ChildItem $UncPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum / 1GB
}
catch {
Write-Warning "Could not get the file size for '$uncPath'"
$Size = 0
}
# output the details
[PSCustomObject]#{
'Name' = $_.Name
'LocalPath' = $_.Path
'UNCPath' = $UncPath
'Description' = $_.Description
'Size' = '{0:N2} GB' -f $Size # format the size to two decimals
}
}
}
}
Get-ShareSize -ComputerName localhost
Hope that helps
GOAL: Obtain a CSV file with the following information:
Computer Name
Share Name
Share Path
Share Description
for all non-admin (type 0) SMB shares on all servers from a list (txt file).
INITIAL CODE:
param (
[Parameter(Mandatory=$true,Position=0)]
[ValidateNotNullOrEmpty()]
[String]
$path
)
$computers = Get-Content $path
$shareInfo = #()
ForEach ($computer in $computers) {
$shares = gwmi -Computer $computer -Class Win32_Share -filter "Type = 0" | Select Name,Path,Description
$shares | % {
$ShareName = $_.Name
$Props = [ordered]#{
Computer = $computer
ShareName = $_.Name
Path = $shares.Path
Description = $shares.Description
}
}
$ShareInfo += New-Object -TypeName PSObject -Property $Props
}
$shareInfo | Export-CSV -Path .\shares.csv -NoType
CODE OUTPUT:
"Computer","ShareName","Path","Description"
"SERVER1","SHARE1","System.Object[]","System.Object[]"
"SERVER2","SHARE12","System.Object[]","System.Object[]"
"SERVER3","SHARE3","System.Object[]","System.Object[]"
PROBLEM:
While the code provides output for each server, it seems to not include all shares from the servers. Furthermore, the Path and Description fields are not populated with good information.
ADDITIONAL INFO:
The code:
$shares = gwmi -Computer $computer -Class Win32_Share -filter "Type = 0" | Select Name,Path,Description
Produces good information as below:
Name Path Description
---- ---- -----------
print$ C:\WINDOWS\system32\spool\drivers Printer Drivers
Share D:\Share
SHARE2 D:\SHARE2
Software C:\Software The Software
$shares | % {
$ShareName = $_.Name
$Props = [ordered]#{
Computer = $computer
ShareName = $_.Name
Path = $shares.Path
Description = $shares.Description
}
}
You're using $shares instead of $_ for the Path and Description properties, so each of these properties is assigned a list of the values of the respective property of each element of the $shares collection.
Also, why are you building custom objects in the first place when you just need to filter the WMI query results? The computer name can be obtained from the __SERVER (or PSMachineName) property. Plus, type 0 means a shared disk drive, not an administrative share. You need to filter the latter by other criteria (usually description and/or share name).
$filter = "Type = 0 And Description != 'Default Share' And " +
"Name != 'ADMIN$' And Name != 'IPC$'"
$computers |
ForEach-Object { Get-WmiObject -Computer $_ -Class Win32_Share -Filter $filter } |
Select-Object #{n='Computer';e={$_.__SERVER}}, Name, Path, Description |
Export-Csv -Path .\shares.csv -NoType
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 wrote a script to copy files to the "All Users" desktop or "Public Desktop"
However we have a mixed environment. Some people are using Windows XP and other people are using Windows 7.
$SOURCE = "I:\Path\To\Folder\*"
$DESTINATION7 = "c$\Users\Public\Desktop"
$DESTINATIONXP = "c$\Documents and Settings\All Users\Desktop"
$computerlist = Get-Content I:\Path\To\File\computer-list.csv
$results = #()
$filenotthere = #()
$filesremoved = #()
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
Write-Host "\\$computer\$DESTINATION\"
Copy-Item $SOURCE "\\$computer\$DESTINATION\" -Recurse -force
} else {
$details = #{
Date = get-date
ComputerName = $Computer
Destination = $Destination
}
$results += New-Object PSObject -Property $details
$results | export-csv -Path I:\Path\To\logs\offline.txt -NoTypeInformation -Append
}
}
DESTINATION is empty. Expanding on Keith's suggestion:
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
$OS = Get-WmiObject -Computer $computer -Class Win32_OperatingSystem
if($OS.caption -like '*Windows 7*'){
$DESTINATION = $DESTINATION7
}
if($OS.caption -like '*Windows XP*'){
$DESTINATION = $DESTINATIONXP
}
}
}
This could avoid the error you're getting also. empty $DESTINATION.
In your foreach loop through $computerlist you can grab the OS Caption for each computer by using WMI:
$OS = Get-WmiObject -Computer $computer -Class Win32_OperatingSystem
Ant then check the $OS
if($OS.caption -like '*Windows 7*'){
#Code here for Windows 7
}
#....
I had a slightly different goal...But thanks for the basics.
del C:\scripts\OS.csv
$computerlist = Get-Content c:\scripts\computerlist.csv
foreach ($computer in $computerlist) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{
Get-WMIObject Win32_OperatingSystem -ComputerName $computer |
select-object CSName, Caption, CSDVersion, OSType, LastBootUpTime, ProductType| export-csv -Path C:\Scripts\OS.csv -NoTypeInformation -Append
}
}